Add validation for currencies to validator (#1797)

* Add validation for currencies to validator

* Add changelog
This commit is contained in:
James Agnew 2020-04-09 11:39:30 -04:00 committed by GitHub
parent 8cdc3a72ce
commit fdf6633145
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 257 additions and 21 deletions

View File

@ -0,0 +1,4 @@
---
type: add
issue: 1797
title: The HAPI FHIR instance validator now includes validation for currency types (ISO 4217)

View File

@ -24,9 +24,12 @@ import java.util.Map;
public class CommonCodeSystemsTerminologyService implements IValidationSupport { public class CommonCodeSystemsTerminologyService implements IValidationSupport {
public static final String LANGUAGES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/languages"; public static final String LANGUAGES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/languages";
public static final String MIMETYPES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/mimetypes"; public static final String MIMETYPES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/mimetypes";
public static final String CURRENCIES_CODESYSTEM_URL = "urn:iso:std:iso:4217";
public static final String CURRENCIES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/currencies";
private static final String USPS_CODESYSTEM_URL = "https://www.usps.com/"; private static final String USPS_CODESYSTEM_URL = "https://www.usps.com/";
private static final String USPS_VALUESET_URL = "http://hl7.org/fhir/us/core/ValueSet/us-core-usps-state"; private static final String USPS_VALUESET_URL = "http://hl7.org/fhir/us/core/ValueSet/us-core-usps-state";
private static Map<String, String> USPS_CODES = Collections.unmodifiableMap(buildUspsCodes()); private static Map<String, String> USPS_CODES = Collections.unmodifiableMap(buildUspsCodes());
private static Map<String, String> ISO_4217_CODES = Collections.unmodifiableMap(buildIso4217Codes());
private final FhirContext myFhirContext; private final FhirContext myFhirContext;
@ -49,34 +52,38 @@ public class CommonCodeSystemsTerminologyService implements IValidationSupport {
* changes in any way! * changes in any way!
* **************************************************************************************/ * **************************************************************************************/
boolean handled = false; Map<String, String> handlerMap = null;
if (USPS_VALUESET_URL.equals(url)) { String expectSystem = null;
handled = true; switch (url) {
String display = USPS_CODES.get(theCode); case USPS_VALUESET_URL:
handlerMap = USPS_CODES;
expectSystem = USPS_CODESYSTEM_URL;
break;
case CURRENCIES_VALUESET_URL:
handlerMap = ISO_4217_CODES;
expectSystem = CURRENCIES_CODESYSTEM_URL;
break;
case LANGUAGES_VALUESET_URL:
case MIMETYPES_VALUESET_URL:
// This is a pretty naive implementation - Should be enhanced in future
return new CodeValidationResult()
.setCode(theCode)
.setDisplay(theDisplay);
}
if (handlerMap != null) {
String display = handlerMap.get(theCode);
if (display != null) { if (display != null) {
if (USPS_CODESYSTEM_URL.equals(theCodeSystem) || theOptions.isInferSystem()) { if (expectSystem.equals(theCodeSystem) || theOptions.isInferSystem()) {
return new CodeValidationResult() return new CodeValidationResult()
.setCode(theCode) .setCode(theCode)
.setDisplay(display); .setDisplay(display);
} }
} }
}
// This is a pretty naive implementation - Will be enhanced in future
if (LANGUAGES_VALUESET_URL.equals(url)) {
return new CodeValidationResult()
.setCode(theCode)
.setDisplay(theDisplay);
}
// This is a pretty naive implementation - Will be enhanced in future
if (MIMETYPES_VALUESET_URL.equals(url)) {
return new CodeValidationResult()
.setCode(theCode)
.setDisplay(theDisplay);
}
if (handled) {
return new CodeValidationResult() return new CodeValidationResult()
.setSeverity(IssueSeverity.ERROR) .setSeverity(IssueSeverity.ERROR)
.setMessage("Code \"" + theCode + "\" is not in system: " + USPS_CODESYSTEM_URL); .setMessage("Code \"" + theCode + "\" is not in system: " + USPS_CODESYSTEM_URL);
@ -184,4 +191,192 @@ public class CommonCodeSystemsTerminologyService implements IValidationSupport {
uspsCodes.put("WY", "Wyoming"); uspsCodes.put("WY", "Wyoming");
return uspsCodes; return uspsCodes;
} }
private static HashMap<String, String> buildIso4217Codes() {
HashMap<String, String> iso4217Codes = new HashMap<>();
iso4217Codes.put("AED", "United Arab Emirates dirham");
iso4217Codes.put("AFN", "Afghan afghani");
iso4217Codes.put("ALL", "Albanian lek");
iso4217Codes.put("AMD", "Armenian dram");
iso4217Codes.put("ANG", "Netherlands Antillean guilder");
iso4217Codes.put("AOA", "Angolan kwanza");
iso4217Codes.put("ARS", "Argentine peso");
iso4217Codes.put("AUD", "Australian dollar");
iso4217Codes.put("AWG", "Aruban florin");
iso4217Codes.put("AZN", "Azerbaijani manat");
iso4217Codes.put("BAM", "Bosnia and Herzegovina convertible mark");
iso4217Codes.put("BBD", "Barbados dollar");
iso4217Codes.put("BDT", "Bangladeshi taka");
iso4217Codes.put("BGN", "Bulgarian lev");
iso4217Codes.put("BHD", "Bahraini dinar");
iso4217Codes.put("BIF", "Burundian franc");
iso4217Codes.put("BMD", "Bermudian dollar");
iso4217Codes.put("BND", "Brunei dollar");
iso4217Codes.put("BOB", "Boliviano");
iso4217Codes.put("BOV", "Bolivian Mvdol (funds code)");
iso4217Codes.put("BRL", "Brazilian real");
iso4217Codes.put("BSD", "Bahamian dollar");
iso4217Codes.put("BTN", "Bhutanese ngultrum");
iso4217Codes.put("BWP", "Botswana pula");
iso4217Codes.put("BYN", "Belarusian ruble");
iso4217Codes.put("BZD", "Belize dollar");
iso4217Codes.put("CAD", "Canadian dollar");
iso4217Codes.put("CDF", "Congolese franc");
iso4217Codes.put("CHE", "WIR Euro (complementary currency)");
iso4217Codes.put("CHF", "Swiss franc");
iso4217Codes.put("CHW", "WIR Franc (complementary currency)");
iso4217Codes.put("CLF", "Unidad de Fomento (funds code)");
iso4217Codes.put("CLP", "Chilean peso");
iso4217Codes.put("CNY", "Renminbi (Chinese) yuan[8]");
iso4217Codes.put("COP", "Colombian peso");
iso4217Codes.put("COU", "Unidad de Valor Real (UVR) (funds code)[9]");
iso4217Codes.put("CRC", "Costa Rican colon");
iso4217Codes.put("CUC", "Cuban convertible peso");
iso4217Codes.put("CUP", "Cuban peso");
iso4217Codes.put("CVE", "Cape Verde escudo");
iso4217Codes.put("CZK", "Czech koruna");
iso4217Codes.put("DJF", "Djiboutian franc");
iso4217Codes.put("DKK", "Danish krone");
iso4217Codes.put("DOP", "Dominican peso");
iso4217Codes.put("DZD", "Algerian dinar");
iso4217Codes.put("EGP", "Egyptian pound");
iso4217Codes.put("ERN", "Eritrean nakfa");
iso4217Codes.put("ETB", "Ethiopian birr");
iso4217Codes.put("EUR", "Euro");
iso4217Codes.put("FJD", "Fiji dollar");
iso4217Codes.put("FKP", "Falkland Islands pound");
iso4217Codes.put("GBP", "Pound sterling");
iso4217Codes.put("GEL", "Georgian lari");
iso4217Codes.put("GGP", "Guernsey Pound");
iso4217Codes.put("GHS", "Ghanaian cedi");
iso4217Codes.put("GIP", "Gibraltar pound");
iso4217Codes.put("GMD", "Gambian dalasi");
iso4217Codes.put("GNF", "Guinean franc");
iso4217Codes.put("GTQ", "Guatemalan quetzal");
iso4217Codes.put("GYD", "Guyanese dollar");
iso4217Codes.put("HKD", "Hong Kong dollar");
iso4217Codes.put("HNL", "Honduran lempira");
iso4217Codes.put("HRK", "Croatian kuna");
iso4217Codes.put("HTG", "Haitian gourde");
iso4217Codes.put("HUF", "Hungarian forint");
iso4217Codes.put("IDR", "Indonesian rupiah");
iso4217Codes.put("ILS", "Israeli new shekel");
iso4217Codes.put("IMP", "Isle of Man Pound");
iso4217Codes.put("INR", "Indian rupee");
iso4217Codes.put("IQD", "Iraqi dinar");
iso4217Codes.put("IRR", "Iranian rial");
iso4217Codes.put("ISK", "Icelandic króna");
iso4217Codes.put("JEP", "Jersey Pound");
iso4217Codes.put("JMD", "Jamaican dollar");
iso4217Codes.put("JOD", "Jordanian dinar");
iso4217Codes.put("JPY", "Japanese yen");
iso4217Codes.put("KES", "Kenyan shilling");
iso4217Codes.put("KGS", "Kyrgyzstani som");
iso4217Codes.put("KHR", "Cambodian riel");
iso4217Codes.put("KMF", "Comoro franc");
iso4217Codes.put("KPW", "North Korean won");
iso4217Codes.put("KRW", "South Korean won");
iso4217Codes.put("KWD", "Kuwaiti dinar");
iso4217Codes.put("KYD", "Cayman Islands dollar");
iso4217Codes.put("KZT", "Kazakhstani tenge");
iso4217Codes.put("LAK", "Lao kip");
iso4217Codes.put("LBP", "Lebanese pound");
iso4217Codes.put("LKR", "Sri Lankan rupee");
iso4217Codes.put("LRD", "Liberian dollar");
iso4217Codes.put("LSL", "Lesotho loti");
iso4217Codes.put("LYD", "Libyan dinar");
iso4217Codes.put("MAD", "Moroccan dirham");
iso4217Codes.put("MDL", "Moldovan leu");
iso4217Codes.put("MGA", "Malagasy ariary");
iso4217Codes.put("MKD", "Macedonian denar");
iso4217Codes.put("MMK", "Myanmar kyat");
iso4217Codes.put("MNT", "Mongolian tögrög");
iso4217Codes.put("MOP", "Macanese pataca");
iso4217Codes.put("MRU", "Mauritanian ouguiya");
iso4217Codes.put("MUR", "Mauritian rupee");
iso4217Codes.put("MVR", "Maldivian rufiyaa");
iso4217Codes.put("MWK", "Malawian kwacha");
iso4217Codes.put("MXN", "Mexican peso");
iso4217Codes.put("MXV", "Mexican Unidad de Inversion (UDI) (funds code)");
iso4217Codes.put("MYR", "Malaysian ringgit");
iso4217Codes.put("MZN", "Mozambican metical");
iso4217Codes.put("NAD", "Namibian dollar");
iso4217Codes.put("NGN", "Nigerian naira");
iso4217Codes.put("NIO", "Nicaraguan córdoba");
iso4217Codes.put("NOK", "Norwegian krone");
iso4217Codes.put("NPR", "Nepalese rupee");
iso4217Codes.put("NZD", "New Zealand dollar");
iso4217Codes.put("OMR", "Omani rial");
iso4217Codes.put("PAB", "Panamanian balboa");
iso4217Codes.put("PEN", "Peruvian Sol");
iso4217Codes.put("PGK", "Papua New Guinean kina");
iso4217Codes.put("PHP", "Philippine piso[13]");
iso4217Codes.put("PKR", "Pakistani rupee");
iso4217Codes.put("PLN", "Polish złoty");
iso4217Codes.put("PYG", "Paraguayan guaraní");
iso4217Codes.put("QAR", "Qatari riyal");
iso4217Codes.put("RON", "Romanian leu");
iso4217Codes.put("RSD", "Serbian dinar");
iso4217Codes.put("RUB", "Russian ruble");
iso4217Codes.put("RWF", "Rwandan franc");
iso4217Codes.put("SAR", "Saudi riyal");
iso4217Codes.put("SBD", "Solomon Islands dollar");
iso4217Codes.put("SCR", "Seychelles rupee");
iso4217Codes.put("SDG", "Sudanese pound");
iso4217Codes.put("SEK", "Swedish krona/kronor");
iso4217Codes.put("SGD", "Singapore dollar");
iso4217Codes.put("SHP", "Saint Helena pound");
iso4217Codes.put("SLL", "Sierra Leonean leone");
iso4217Codes.put("SOS", "Somali shilling");
iso4217Codes.put("SRD", "Surinamese dollar");
iso4217Codes.put("SSP", "South Sudanese pound");
iso4217Codes.put("STN", "São Tomé and Príncipe dobra");
iso4217Codes.put("SVC", "Salvadoran colón");
iso4217Codes.put("SYP", "Syrian pound");
iso4217Codes.put("SZL", "Swazi lilangeni");
iso4217Codes.put("THB", "Thai baht");
iso4217Codes.put("TJS", "Tajikistani somoni");
iso4217Codes.put("TMT", "Turkmenistan manat");
iso4217Codes.put("TND", "Tunisian dinar");
iso4217Codes.put("TOP", "Tongan paʻanga");
iso4217Codes.put("TRY", "Turkish lira");
iso4217Codes.put("TTD", "Trinidad and Tobago dollar");
iso4217Codes.put("TVD", "Tuvalu Dollar");
iso4217Codes.put("TWD", "New Taiwan dollar");
iso4217Codes.put("TZS", "Tanzanian shilling");
iso4217Codes.put("UAH", "Ukrainian hryvnia");
iso4217Codes.put("UGX", "Ugandan shilling");
iso4217Codes.put("USD", "United States dollar");
iso4217Codes.put("USN", "United States dollar (next day) (funds code)");
iso4217Codes.put("UYI", "Uruguay Peso en Unidades Indexadas (URUIURUI) (funds code)");
iso4217Codes.put("UYU", "Uruguayan peso");
iso4217Codes.put("UZS", "Uzbekistan som");
iso4217Codes.put("VEF", "Venezuelan bolívar");
iso4217Codes.put("VND", "Vietnamese đồng");
iso4217Codes.put("VUV", "Vanuatu vatu");
iso4217Codes.put("WST", "Samoan tala");
iso4217Codes.put("XAF", "CFA franc BEAC");
iso4217Codes.put("XAG", "Silver (one troy ounce)");
iso4217Codes.put("XAU", "Gold (one troy ounce)");
iso4217Codes.put("XBA", "European Composite Unit (EURCO) (bond market unit)");
iso4217Codes.put("XBB", "European Monetary Unit (E.M.U.-6) (bond market unit)");
iso4217Codes.put("XBC", "European Unit of Account 9 (E.U.A.-9) (bond market unit)");
iso4217Codes.put("XBD", "European Unit of Account 17 (E.U.A.-17) (bond market unit)");
iso4217Codes.put("XCD", "East Caribbean dollar");
iso4217Codes.put("XDR", "Special drawing rights");
iso4217Codes.put("XOF", "CFA franc BCEAO");
iso4217Codes.put("XPD", "Palladium (one troy ounce)");
iso4217Codes.put("XPF", "CFP franc (franc Pacifique)");
iso4217Codes.put("XPT", "Platinum (one troy ounce)");
iso4217Codes.put("XSU", "SUCRE");
iso4217Codes.put("XTS", "Code reserved for testing purposes");
iso4217Codes.put("XUA", "ADB Unit of Account");
iso4217Codes.put("XXX", "No currency");
iso4217Codes.put("YER", "Yemeni rial");
iso4217Codes.put("ZAR", "South African rand");
iso4217Codes.put("ZMW", "Zambian kwacha");
iso4217Codes.put("ZWL", "Zimbabwean dollar A/10");
return iso4217Codes;
}
} }

View File

@ -1301,6 +1301,43 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
ourLog.info(output.getMessages().get(0).getMessage()); ourLog.info(output.getMessages().get(0).getMessage());
} }
@Test
public void testValidateCurrency() {
String input = "{\n" +
" \"resourceType\": \"Invoice\",\n" +
" \"status\": \"draft\",\n" +
" \"date\": \"2020-01-08\",\n" +
" \"totalGross\": {\n" +
" \"value\": 150,\n" +
" \"currency\": \"USD\"\n" +
" }\n" +
"}";
ValidationResult output = myVal.validateWithResult(input);
List<SingleValidationMessage> errors = logResultsAndReturnNonInformationalOnes(output);
assertEquals(errors.toString(), 0, errors.size());
}
@Test
public void testValidateCurrency_Wrong() {
String input = "{\n" +
" \"resourceType\": \"Invoice\",\n" +
" \"status\": \"draft\",\n" +
" \"date\": \"2020-01-08\",\n" +
" \"totalGross\": {\n" +
" \"value\": 150,\n" +
" \"currency\": \"BLAH\"\n" +
" }\n" +
"}";
ValidationResult output = myVal.validateWithResult(input);
List<SingleValidationMessage> errors = logResultsAndReturnNonInformationalOnes(output);
assertEquals(errors.toString(), 1, errors.size());
assertThat(errors.get(0).getMessage(), containsString("The value provided (\"BLAH\") is not in the value set http://hl7.org/fhir/ValueSet/currencies"));
}
@AfterClass @AfterClass
public static void afterClassClearContext() { public static void afterClassClearContext() {
myDefaultValidationSupport.flush(); myDefaultValidationSupport.flush();