001package org.hl7.fhir.common.hapi.validation.support; 002 003import ca.uhn.fhir.context.ConfigurationException; 004import ca.uhn.fhir.context.FhirContext; 005import ca.uhn.fhir.context.FhirVersionEnum; 006import ca.uhn.fhir.context.support.ConceptValidationOptions; 007import ca.uhn.fhir.context.support.IValidationSupport; 008import ca.uhn.fhir.context.support.LookupCodeRequest; 009import ca.uhn.fhir.context.support.ValidationSupportContext; 010import ca.uhn.fhir.i18n.Msg; 011import ca.uhn.fhir.util.ClasspathUtil; 012import ca.uhn.hapi.converters.canonical.VersionCanonicalizer; 013import com.fasterxml.jackson.core.JsonProcessingException; 014import com.fasterxml.jackson.databind.ObjectMapper; 015import com.fasterxml.jackson.databind.node.ArrayNode; 016import com.fasterxml.jackson.databind.node.ObjectNode; 017import jakarta.annotation.Nonnull; 018import jakarta.annotation.Nullable; 019import org.apache.commons.lang3.StringUtils; 020import org.fhir.ucum.UcumEssenceService; 021import org.fhir.ucum.UcumException; 022import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_40; 023import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50; 024import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_43_50; 025import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40; 026import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50; 027import org.hl7.fhir.convertors.factory.VersionConvertorFactory_43_50; 028import org.hl7.fhir.dstu2.model.ValueSet; 029import org.hl7.fhir.instance.model.api.IBaseResource; 030import org.hl7.fhir.r4.model.CodeSystem; 031import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode; 032import org.hl7.fhir.r5.model.Resource; 033import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037import java.io.IOException; 038import java.io.InputStream; 039import java.util.Collections; 040import java.util.HashMap; 041import java.util.Map; 042import java.util.Objects; 043import java.util.Optional; 044 045import static org.apache.commons.lang3.StringUtils.defaultString; 046import static org.apache.commons.lang3.StringUtils.isBlank; 047import static org.apache.commons.lang3.StringUtils.isNotBlank; 048 049/** 050 * This {@link IValidationSupport validation support module} can be used to validate codes against common 051 * CodeSystems that are commonly used, but are not distriuted with the FHIR specification for various reasons 052 * (size, complexity, etc.). 053 * <p> 054 * See <a href="https://hapifhir.io/hapi-fhir/docs/validation/validation_support_modules.html#CommonCodeSystemsTerminologyService">CommonCodeSystemsTerminologyService</a> in the HAPI FHIR documentation 055 * for details about what is and isn't covered by this class. 056 * </p> 057 */ 058@SuppressWarnings("EnhancedSwitchMigration") 059public class CommonCodeSystemsTerminologyService implements IValidationSupport { 060 public static final String LANGUAGES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/languages"; 061 public static final String LANGUAGES_CODESYSTEM_URL = "urn:ietf:bcp:47"; 062 public static final String MIMETYPES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/mimetypes"; 063 public static final String MIMETYPES_CODESYSTEM_URL = "urn:ietf:bcp:13"; 064 public static final String CURRENCIES_CODESYSTEM_URL = "urn:iso:std:iso:4217"; 065 public static final String CURRENCIES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/currencies"; 066 public static final String COUNTRIES_CODESYSTEM_URL = "urn:iso:std:iso:3166"; 067 public static final String UCUM_CODESYSTEM_URL = "http://unitsofmeasure.org"; 068 public static final String UCUM_VALUESET_URL = "http://hl7.org/fhir/ValueSet/ucum-units"; 069 public static final String ALL_LANGUAGES_VALUESET_URL = "http://hl7.org/fhir/ValueSet/all-languages"; 070 public static final String USPS_CODESYSTEM_URL = "https://www.usps.com/"; 071 public static final String USPS_VALUESET_URL = "http://hl7.org/fhir/us/core/ValueSet/us-core-usps-state"; 072 private static final Logger ourLog = LoggerFactory.getLogger(CommonCodeSystemsTerminologyService.class); 073 private static final Map<String, String> USPS_CODES = Collections.unmodifiableMap(buildUspsCodes()); 074 private static final Map<String, String> ISO_4217_CODES = Collections.unmodifiableMap(buildIso4217Codes()); 075 private static final Map<String, String> ISO_3166_CODES = Collections.unmodifiableMap(buildIso3166Codes()); 076 private final FhirContext myFhirContext; 077 private final VersionCanonicalizer myVersionCanonicalizer; 078 private volatile org.hl7.fhir.r5.model.ValueSet myLanguagesVs; 079 private volatile Map<String, String> myLanguagesLanugageMap; 080 private volatile Map<String, String> myLanguagesRegionMap; 081 082 /** 083 * Constructor 084 */ 085 public CommonCodeSystemsTerminologyService(FhirContext theFhirContext) { 086 Objects.requireNonNull(theFhirContext); 087 myFhirContext = theFhirContext; 088 myVersionCanonicalizer = new VersionCanonicalizer(theFhirContext); 089 } 090 091 @Override 092 public String getName() { 093 return myFhirContext.getVersion().getVersion() + " Common Code Systems Validation Support"; 094 } 095 096 @Override 097 public CodeValidationResult validateCodeInValueSet( 098 ValidationSupportContext theValidationSupportContext, 099 ConceptValidationOptions theOptions, 100 String theCodeSystem, 101 String theCode, 102 String theDisplay, 103 @Nonnull IBaseResource theValueSet) { 104 String url = getValueSetUrl(getFhirContext(), theValueSet); 105 return validateCode(theValidationSupportContext, theOptions, theCodeSystem, theCode, theDisplay, url); 106 } 107 108 @Override 109 public CodeValidationResult validateCode( 110 @Nonnull ValidationSupportContext theValidationSupportContext, 111 @Nonnull ConceptValidationOptions theOptions, 112 final String theCodeSystem, 113 final String theCode, 114 final String theDisplay, 115 final String theValueSetUrl) { 116 /* ************************************************************************************** 117 * NOTE: Update validation_support_modules.md if any of the support in this module 118 * changes in any way! 119 * **************************************************************************************/ 120 121 String valueSet = defaultString(theValueSetUrl); 122 String system = defaultString(theCodeSystem); 123 124 if (!isBlank(valueSet)) { 125 final String expectSystem = getCodeSystemForValueSet(valueSet); 126 if (!isBlank(system) && !system.equals(expectSystem)) { 127 return getValidateCodeResultInError("mismatchCodeSystem", system, valueSet); 128 } 129 system = expectSystem; 130 } 131 132 switch (valueSet) { 133 case USPS_VALUESET_URL: 134 return validateCodeUsingCodeMap(theCode, system, USPS_CODES); 135 case CURRENCIES_VALUESET_URL: 136 return validateCodeUsingCodeMap(theCode, system, ISO_4217_CODES); 137 case LANGUAGES_VALUESET_URL: 138 return validateLanguageCodeInValueSet(theValidationSupportContext, theCode); 139 case ALL_LANGUAGES_VALUESET_URL: 140 return validateLanguageCode(theCode, valueSet); 141 case MIMETYPES_VALUESET_URL: 142 // This is a pretty naive implementation - Should be enhanced in future 143 return getValidateCodeResultOk(theCode, theDisplay); 144 case UCUM_VALUESET_URL: { 145 return validateCodeUsingSystemLookup(theValidationSupportContext, theCode, system); 146 } 147 } 148 149 if (isBlank(valueSet)) { 150 return validateCodeUsingSystemLookup(theValidationSupportContext, theCode, system); 151 } 152 153 return null; 154 } 155 156 private static String getCodeSystemForValueSet(final String theValueSetUrl) { 157 String theCodeSystem = null; 158 switch (defaultString(theValueSetUrl)) { 159 case USPS_VALUESET_URL: 160 theCodeSystem = USPS_CODESYSTEM_URL; 161 break; 162 case CURRENCIES_VALUESET_URL: 163 theCodeSystem = CURRENCIES_CODESYSTEM_URL; 164 break; 165 case LANGUAGES_VALUESET_URL: 166 case ALL_LANGUAGES_VALUESET_URL: 167 theCodeSystem = LANGUAGES_CODESYSTEM_URL; 168 break; 169 case MIMETYPES_VALUESET_URL: 170 theCodeSystem = MIMETYPES_CODESYSTEM_URL; 171 break; 172 case UCUM_VALUESET_URL: 173 theCodeSystem = UCUM_CODESYSTEM_URL; 174 break; 175 } 176 return theCodeSystem; 177 } 178 179 protected CodeValidationResult getValidateCodeResultInError( 180 final String errorCode, final String theFirstParam, final String theSecondParam) { 181 String message = getErrorMessage(errorCode, theFirstParam, theSecondParam); 182 return getValidateCodeResultError(message); 183 } 184 185 protected CodeValidationResult getValidateCodeResultOk(final String theCode, final String theDisplay) { 186 return new CodeValidationResult().setCode(theCode).setDisplay(theDisplay); 187 } 188 189 protected CodeValidationResult getValidateCodeResultError(final String theMessage) { 190 return new CodeValidationResult().setSeverity(IssueSeverity.ERROR).setMessage(theMessage); 191 } 192 193 private CodeValidationResult validateCodeUsingCodeMap( 194 final String theCode, final String theSystem, final Map<String, String> theCodeMap) { 195 if (theCodeMap.containsKey(theCode)) { 196 return getValidateCodeResultOk(theCode, theCodeMap.get(theCode)); 197 } else { 198 return getValidateCodeResultInError("unknownCodeInSystem", theSystem, theCode); 199 } 200 } 201 202 @Nullable 203 public CodeValidationResult validateCodeUsingSystemLookup( 204 final ValidationSupportContext theValidationSupportContext, final String theCode, final String theSystem) { 205 LookupCodeResult result = lookupCode(theValidationSupportContext, new LookupCodeRequest(theSystem, theCode)); 206 if (result == null) { 207 return getValidateCodeResultInError("unknownCodeInSystem", theSystem, theCode); 208 } 209 if (result.isFound()) { 210 return getValidateCodeResultOk(theCode, result.getCodeDisplay()); 211 } else if (result.getErrorMessage() != null) { 212 return getValidateCodeResultError(result.getErrorMessage()); 213 } 214 return null; 215 } 216 217 @Override 218 public LookupCodeResult lookupCode( 219 ValidationSupportContext theValidationSupportContext, @Nonnull LookupCodeRequest theLookupCodeRequest) { 220 final String code = theLookupCodeRequest.getCode(); 221 final String system = theLookupCodeRequest.getSystem(); 222 223 Map<String, String> map; 224 switch (system) { 225 case LANGUAGES_CODESYSTEM_URL: 226 return lookupLanguageCode(code); 227 case UCUM_CODESYSTEM_URL: 228 return lookupUcumCode(code); 229 case MIMETYPES_CODESYSTEM_URL: 230 return lookupMimetypeCode(code); 231 case COUNTRIES_CODESYSTEM_URL: 232 map = ISO_3166_CODES; 233 break; 234 case CURRENCIES_CODESYSTEM_URL: 235 map = ISO_4217_CODES; 236 break; 237 case USPS_CODESYSTEM_URL: 238 map = USPS_CODES; 239 break; 240 default: 241 return null; 242 } 243 244 LookupCodeResult retVal = new LookupCodeResult(); 245 retVal.setSearchedForCode(code); 246 retVal.setSearchedForSystem(system); 247 248 String display = map.get(code); 249 if (isNotBlank(display)) { 250 retVal.setFound(true); 251 retVal.setCodeDisplay(display); 252 } else { 253 // If we get here it means we know the CodeSystem but the code was bad 254 retVal.setFound(false); 255 String invalidCodeMessage = getErrorMessage("invalidCodeInSystem", code, system); 256 retVal.setErrorMessage(invalidCodeMessage); 257 } 258 259 return retVal; 260 } 261 262 private CodeValidationResult validateLanguageCode(final String theCode, final String theValueSetUrl) { 263 LookupCodeResult outcome = lookupLanguageCode(theCode); 264 if (outcome.isFound()) { 265 return getValidateCodeResultOk(theCode, outcome.getCodeDisplay()); 266 } else { 267 return getValidateCodeResultInError("codeNotFoundInValueSet", theCode, theValueSetUrl); 268 } 269 } 270 271 private CodeValidationResult validateLanguageCodeInValueSet( 272 final ValidationSupportContext theValidationSupportContext, final String theCode) { 273 final String valueSet = LANGUAGES_VALUESET_URL; 274 if (myLanguagesVs == null) { 275 IBaseResource languagesVs = 276 theValidationSupportContext.getRootValidationSupport().fetchValueSet(valueSet); 277 myLanguagesVs = myVersionCanonicalizer.valueSetToValidatorCanonical(languagesVs); 278 } 279 Optional<ConceptReferenceComponent> match = myLanguagesVs.getCompose().getInclude().stream() 280 .flatMap(t -> t.getConcept().stream()) 281 .filter(t -> theCode.equals(t.getCode())) 282 .findFirst(); 283 if (match.isPresent()) { 284 return getValidateCodeResultOk(theCode, match.get().getDisplay()); 285 } else { 286 return getValidateCodeResultInError("codeNotFoundInValueSet", theCode, valueSet); 287 } 288 } 289 290 private LookupCodeResult lookupLanguageCode(String theCode) { 291 if (myLanguagesLanugageMap == null || myLanguagesRegionMap == null) { 292 initializeBcp47LanguageMap(); 293 } 294 295 final LookupCodeResult lookupCodeResult = new LookupCodeResult(); 296 lookupCodeResult.setSearchedForSystem(LANGUAGES_CODESYSTEM_URL); 297 lookupCodeResult.setSearchedForCode(theCode); 298 299 final int langRegionSeparatorIndex = StringUtils.indexOfAny(theCode, '-', '_'); 300 final boolean hasRegionAndCodeSegments = langRegionSeparatorIndex > 0; 301 302 final boolean found; 303 final String display; 304 305 if (hasRegionAndCodeSegments) { 306 // we look for languages in lowercase only 307 // this will allow case insensitivity for language portion of code 308 String language = myLanguagesLanugageMap.get( 309 theCode.substring(0, langRegionSeparatorIndex).toLowerCase()); 310 String region = myLanguagesRegionMap.get( 311 theCode.substring(langRegionSeparatorIndex + 1).toUpperCase()); 312 313 // In case the user provides both a language and a region, they must both be valid for the lookup to 314 // succeed. 315 found = language != null && region != null; 316 display = found ? language + " " + region : null; 317 if (!found) { 318 ourLog.warn("Couldn't find a valid bcp47 language-region combination from code: {}", theCode); 319 } 320 } else { 321 // In case user has only provided a language, we build the lookup from only that. 322 // NB: we only use the lowercase version of the language 323 String language = myLanguagesLanugageMap.get(theCode.toLowerCase()); 324 found = language != null; 325 display = language; 326 if (!found) { 327 ourLog.warn("Couldn't find a valid bcp47 language from code: {}", theCode); 328 } 329 } 330 331 lookupCodeResult.setFound(found); 332 lookupCodeResult.setCodeDisplay(display); 333 334 return lookupCodeResult; 335 } 336 337 private void initializeBcp47LanguageMap() { 338 Map<String, String> regionsMap; 339 Map<String, String> languagesMap; 340 ourLog.info("Loading BCP47 Language Registry"); 341 342 String input = ClasspathUtil.loadResource("org/hl7/fhir/common/hapi/validation/support/registry.json"); 343 ArrayNode map; 344 try { 345 map = (ArrayNode) new ObjectMapper().readTree(input); 346 } catch (JsonProcessingException e) { 347 throw new ConfigurationException(Msg.code(694) + e); 348 } 349 350 languagesMap = new HashMap<>(); 351 regionsMap = new HashMap<>(); 352 353 for (int i = 0; i < map.size(); i++) { 354 ObjectNode next = (ObjectNode) map.get(i); 355 String type = next.get("Type").asText(); 356 if ("language".equals(type)) { 357 populateSubTagMap(languagesMap, next); 358 } 359 if ("region".equals(type)) { 360 populateSubTagMap(regionsMap, next); 361 } 362 } 363 364 ourLog.info("Have {} languages and {} regions", languagesMap.size(), regionsMap.size()); 365 366 myLanguagesLanugageMap = languagesMap; 367 myLanguagesRegionMap = regionsMap; 368 } 369 370 private void populateSubTagMap(Map<String, String> theLanguagesMap, ObjectNode theNext) { 371 String language = theNext.get("Subtag").asText(); 372 ArrayNode descriptions = (ArrayNode) theNext.get("Description"); 373 String description = null; 374 if (!descriptions.isEmpty()) { 375 description = descriptions.get(0).asText(); 376 } 377 theLanguagesMap.put(language, description); 378 } 379 380 @Nonnull 381 private LookupCodeResult lookupMimetypeCode(String theCode) { 382 // This is a pretty naive implementation - Should be enhanced in future 383 LookupCodeResult mimeRetVal = new LookupCodeResult(); 384 mimeRetVal.setSearchedForCode(theCode); 385 mimeRetVal.setSearchedForSystem(MIMETYPES_CODESYSTEM_URL); 386 mimeRetVal.setFound(true); 387 return mimeRetVal; 388 } 389 390 @Nonnull 391 private LookupCodeResult lookupUcumCode(String theCode) { 392 LookupCodeResult retVal = new LookupCodeResult(); 393 retVal.setSearchedForCode(theCode); 394 retVal.setSearchedForSystem(UCUM_CODESYSTEM_URL); 395 396 try (InputStream input = ClasspathUtil.loadResourceAsStream("/ucum-essence.xml")) { 397 UcumEssenceService svc = new UcumEssenceService(input); 398 String outcome = svc.analyse(theCode); 399 if (outcome != null) { 400 retVal.setFound(true); 401 retVal.setCodeDisplay(outcome); 402 } 403 } catch (UcumException | IOException e) { 404 ourLog.debug("Failed parse UCUM code: {}", theCode, e); 405 retVal.setErrorMessage(e.getMessage()); 406 } 407 return retVal; 408 } 409 410 @Override 411 public IBaseResource fetchCodeSystem(String theSystem) { 412 final CodeSystemContentMode content; 413 Map<String, String> map; 414 switch (defaultString(theSystem)) { 415 case COUNTRIES_CODESYSTEM_URL: 416 map = ISO_3166_CODES; 417 content = CodeSystemContentMode.COMPLETE; 418 break; 419 case CURRENCIES_CODESYSTEM_URL: 420 map = ISO_4217_CODES; 421 content = CodeSystemContentMode.COMPLETE; 422 break; 423 case MIMETYPES_CODESYSTEM_URL: 424 map = Collections.emptyMap(); 425 content = CodeSystemContentMode.NOTPRESENT; 426 break; 427 default: 428 return null; 429 } 430 431 CodeSystem retVal = new CodeSystem(); 432 retVal.setContent(content); 433 retVal.setUrl(theSystem); 434 for (Map.Entry<String, String> nextEntry : map.entrySet()) { 435 retVal.addConcept().setCode(nextEntry.getKey()).setDisplay(nextEntry.getValue()); 436 } 437 438 IBaseResource normalized = null; 439 switch (getFhirContext().getVersion().getVersion()) { 440 case DSTU2: 441 case DSTU2_HL7ORG: 442 case DSTU2_1: 443 return null; 444 case DSTU3: 445 normalized = VersionConvertorFactory_30_40.convertResource(retVal, new BaseAdvisor_30_40(false)); 446 break; 447 case R4: 448 normalized = retVal; 449 break; 450 case R4B: 451 Resource normalized50 = 452 VersionConvertorFactory_40_50.convertResource(retVal, new BaseAdvisor_40_50(false)); 453 normalized = VersionConvertorFactory_43_50.convertResource(normalized50, new BaseAdvisor_43_50()); 454 break; 455 case R5: 456 normalized = VersionConvertorFactory_40_50.convertResource(retVal, new BaseAdvisor_40_50(false)); 457 break; 458 } 459 460 Objects.requireNonNull(normalized); 461 462 return normalized; 463 } 464 465 @Override 466 public boolean isCodeSystemSupported(ValidationSupportContext theValidationSupportContext, String theSystem) { 467 468 switch (theSystem) { 469 case COUNTRIES_CODESYSTEM_URL: 470 case UCUM_CODESYSTEM_URL: 471 case MIMETYPES_CODESYSTEM_URL: 472 case USPS_CODESYSTEM_URL: 473 case LANGUAGES_CODESYSTEM_URL: 474 return true; 475 } 476 477 return false; 478 } 479 480 @Override 481 public boolean isValueSetSupported(ValidationSupportContext theValidationSupportContext, String theValueSetUrl) { 482 483 switch (theValueSetUrl) { 484 case CURRENCIES_VALUESET_URL: 485 case LANGUAGES_VALUESET_URL: 486 case ALL_LANGUAGES_VALUESET_URL: 487 case MIMETYPES_VALUESET_URL: 488 case UCUM_VALUESET_URL: 489 case USPS_VALUESET_URL: 490 return true; 491 } 492 493 return false; 494 } 495 496 @Override 497 public FhirContext getFhirContext() { 498 return myFhirContext; 499 } 500 501 public static String getValueSetUrl(FhirContext theFhirContext, @Nonnull IBaseResource theValueSet) { 502 String url; 503 FhirVersionEnum structureFhirVersionEnum = getFhirVersionEnum(theFhirContext, theValueSet); 504 switch (structureFhirVersionEnum) { 505 case DSTU2: { 506 url = ((ca.uhn.fhir.model.dstu2.resource.ValueSet) theValueSet).getUrl(); 507 break; 508 } 509 case DSTU2_HL7ORG: { 510 url = ((ValueSet) theValueSet).getUrl(); 511 break; 512 } 513 case DSTU3: { 514 url = ((org.hl7.fhir.dstu3.model.ValueSet) theValueSet).getUrl(); 515 break; 516 } 517 case R4: { 518 url = ((org.hl7.fhir.r4.model.ValueSet) theValueSet).getUrl(); 519 break; 520 } 521 case R4B: { 522 url = ((org.hl7.fhir.r4b.model.ValueSet) theValueSet).getUrl(); 523 break; 524 } 525 case R5: { 526 url = ((org.hl7.fhir.r5.model.ValueSet) theValueSet).getUrl(); 527 break; 528 } 529 case DSTU2_1: 530 default: 531 throw new IllegalArgumentException( 532 Msg.code(695) + "Can not handle version: " + structureFhirVersionEnum); 533 } 534 return url; 535 } 536 537 public static String getCodeSystemUrl(@Nonnull FhirContext theFhirContext, @Nonnull IBaseResource theCodeSystem) { 538 String url; 539 FhirVersionEnum structureFhirVersionEnum = getFhirVersionEnum(theFhirContext, theCodeSystem); 540 switch (structureFhirVersionEnum) { 541 case R4: { 542 url = ((org.hl7.fhir.r4.model.CodeSystem) theCodeSystem).getUrl(); 543 break; 544 } 545 case R4B: { 546 url = ((org.hl7.fhir.r4b.model.CodeSystem) theCodeSystem).getUrl(); 547 break; 548 } 549 case R5: { 550 url = ((org.hl7.fhir.r5.model.CodeSystem) theCodeSystem).getUrl(); 551 break; 552 } 553 case DSTU3: 554 default: 555 throw new IllegalArgumentException( 556 Msg.code(696) + "Can not handle version: " + structureFhirVersionEnum); 557 } 558 return url; 559 } 560 561 public static String getValueSetVersion(@Nonnull FhirContext theFhirContext, @Nonnull IBaseResource theValueSet) { 562 String version; 563 switch (getFhirVersionEnum(theFhirContext, theValueSet)) { 564 case DSTU3: { 565 version = ((org.hl7.fhir.dstu3.model.ValueSet) theValueSet).getVersion(); 566 break; 567 } 568 case R4: { 569 version = ((org.hl7.fhir.r4.model.ValueSet) theValueSet).getVersion(); 570 break; 571 } 572 case R4B: { 573 version = ((org.hl7.fhir.r4b.model.ValueSet) theValueSet).getVersion(); 574 break; 575 } 576 case R5: { 577 version = ((org.hl7.fhir.r5.model.ValueSet) theValueSet).getVersion(); 578 break; 579 } 580 case DSTU2: 581 case DSTU2_HL7ORG: 582 case DSTU2_1: 583 default: 584 version = null; 585 } 586 return version; 587 } 588 589 /** 590 * N.B.: We are keeping this as a shim due to the upgrade we did to core 5.6.97+ 591 */ 592 public static FhirVersionEnum getFhirVersionEnum( 593 @Nonnull FhirContext theFhirContext, @Nonnull IBaseResource theResource) { 594 FhirVersionEnum structureFhirVersionEnum = theResource.getStructureFhirVersionEnum(); 595 // TODO: Address this when core lib version is bumped 596 if (theResource.getStructureFhirVersionEnum() == FhirVersionEnum.R5 597 && theFhirContext.getVersion().getVersion() == FhirVersionEnum.R4B) { 598 if (!(theResource instanceof org.hl7.fhir.r5.model.Resource)) { 599 structureFhirVersionEnum = FhirVersionEnum.R4B; 600 } 601 } 602 return structureFhirVersionEnum; 603 } 604 605 private static HashMap<String, String> buildUspsCodes() { 606 HashMap<String, String> uspsCodes = new HashMap<>(); 607 uspsCodes.put("AK", "Alaska"); 608 uspsCodes.put("AL", "Alabama"); 609 uspsCodes.put("AR", "Arkansas"); 610 uspsCodes.put("AS", "American Samoa"); 611 uspsCodes.put("AZ", "Arizona"); 612 uspsCodes.put("CA", "California"); 613 uspsCodes.put("CO", "Colorado"); 614 uspsCodes.put("CT", "Connecticut"); 615 uspsCodes.put("DC", "District of Columbia"); 616 uspsCodes.put("DE", "Delaware"); 617 uspsCodes.put("FL", "Florida"); 618 uspsCodes.put("FM", "Federated States of Micronesia"); 619 uspsCodes.put("GA", "Georgia"); 620 uspsCodes.put("GU", "Guam"); 621 uspsCodes.put("HI", "Hawaii"); 622 uspsCodes.put("IA", "Iowa"); 623 uspsCodes.put("ID", "Idaho"); 624 uspsCodes.put("IL", "Illinois"); 625 uspsCodes.put("IN", "Indiana"); 626 uspsCodes.put("KS", "Kansas"); 627 uspsCodes.put("KY", "Kentucky"); 628 uspsCodes.put("LA", "Louisiana"); 629 uspsCodes.put("MA", "Massachusetts"); 630 uspsCodes.put("MD", "Maryland"); 631 uspsCodes.put("ME", "Maine"); 632 uspsCodes.put("MH", "Marshall Islands"); 633 uspsCodes.put("MI", "Michigan"); 634 uspsCodes.put("MN", "Minnesota"); 635 uspsCodes.put("MO", "Missouri"); 636 uspsCodes.put("MP", "Northern Mariana Islands"); 637 uspsCodes.put("MS", "Mississippi"); 638 uspsCodes.put("MT", "Montana"); 639 uspsCodes.put("NC", "North Carolina"); 640 uspsCodes.put("ND", "North Dakota"); 641 uspsCodes.put("NE", "Nebraska"); 642 uspsCodes.put("NH", "New Hampshire"); 643 uspsCodes.put("NJ", "New Jersey"); 644 uspsCodes.put("NM", "New Mexico"); 645 uspsCodes.put("NV", "Nevada"); 646 uspsCodes.put("NY", "New York"); 647 uspsCodes.put("OH", "Ohio"); 648 uspsCodes.put("OK", "Oklahoma"); 649 uspsCodes.put("OR", "Oregon"); 650 uspsCodes.put("PA", "Pennsylvania"); 651 uspsCodes.put("PR", "Puerto Rico"); 652 uspsCodes.put("PW", "Palau"); 653 uspsCodes.put("RI", "Rhode Island"); 654 uspsCodes.put("SC", "South Carolina"); 655 uspsCodes.put("SD", "South Dakota"); 656 uspsCodes.put("TN", "Tennessee"); 657 uspsCodes.put("TX", "Texas"); 658 uspsCodes.put("UM", "U.S. Minor Outlying Islands"); 659 uspsCodes.put("UT", "Utah"); 660 uspsCodes.put("VA", "Virginia"); 661 uspsCodes.put("VI", "Virgin Islands of the U.S."); 662 uspsCodes.put("VT", "Vermont"); 663 uspsCodes.put("WA", "Washington"); 664 uspsCodes.put("WI", "Wisconsin"); 665 uspsCodes.put("WV", "West Virginia"); 666 uspsCodes.put("WY", "Wyoming"); 667 return uspsCodes; 668 } 669 670 private static HashMap<String, String> buildIso4217Codes() { 671 HashMap<String, String> iso4217Codes = new HashMap<>(); 672 iso4217Codes.put("AED", "United Arab Emirates dirham"); 673 iso4217Codes.put("AFN", "Afghan afghani"); 674 iso4217Codes.put("ALL", "Albanian lek"); 675 iso4217Codes.put("AMD", "Armenian dram"); 676 iso4217Codes.put("ANG", "Netherlands Antillean guilder"); 677 iso4217Codes.put("AOA", "Angolan kwanza"); 678 iso4217Codes.put("ARS", "Argentine peso"); 679 iso4217Codes.put("AUD", "Australian dollar"); 680 iso4217Codes.put("AWG", "Aruban florin"); 681 iso4217Codes.put("AZN", "Azerbaijani manat"); 682 iso4217Codes.put("BAM", "Bosnia and Herzegovina convertible mark"); 683 iso4217Codes.put("BBD", "Barbados dollar"); 684 iso4217Codes.put("BDT", "Bangladeshi taka"); 685 iso4217Codes.put("BGN", "Bulgarian lev"); 686 iso4217Codes.put("BHD", "Bahraini dinar"); 687 iso4217Codes.put("BIF", "Burundian franc"); 688 iso4217Codes.put("BMD", "Bermudian dollar"); 689 iso4217Codes.put("BND", "Brunei dollar"); 690 iso4217Codes.put("BOB", "Boliviano"); 691 iso4217Codes.put("BOV", "Bolivian Mvdol (funds code)"); 692 iso4217Codes.put("BRL", "Brazilian real"); 693 iso4217Codes.put("BSD", "Bahamian dollar"); 694 iso4217Codes.put("BTN", "Bhutanese ngultrum"); 695 iso4217Codes.put("BWP", "Botswana pula"); 696 iso4217Codes.put("BYN", "Belarusian ruble"); 697 iso4217Codes.put("BZD", "Belize dollar"); 698 iso4217Codes.put("CAD", "Canadian dollar"); 699 iso4217Codes.put("CDF", "Congolese franc"); 700 iso4217Codes.put("CHE", "WIR Euro (complementary currency)"); 701 iso4217Codes.put("CHF", "Swiss franc"); 702 iso4217Codes.put("CHW", "WIR Franc (complementary currency)"); 703 iso4217Codes.put("CLF", "Unidad de Fomento (funds code)"); 704 iso4217Codes.put("CLP", "Chilean peso"); 705 iso4217Codes.put("CNY", "Renminbi (Chinese) yuan[8]"); 706 iso4217Codes.put("COP", "Colombian peso"); 707 iso4217Codes.put("COU", "Unidad de Valor Real (UVR) (funds code)[9]"); 708 iso4217Codes.put("CRC", "Costa Rican colon"); 709 iso4217Codes.put("CUC", "Cuban convertible peso"); 710 iso4217Codes.put("CUP", "Cuban peso"); 711 iso4217Codes.put("CVE", "Cape Verde escudo"); 712 iso4217Codes.put("CZK", "Czech koruna"); 713 iso4217Codes.put("DJF", "Djiboutian franc"); 714 iso4217Codes.put("DKK", "Danish krone"); 715 iso4217Codes.put("DOP", "Dominican peso"); 716 iso4217Codes.put("DZD", "Algerian dinar"); 717 iso4217Codes.put("EGP", "Egyptian pound"); 718 iso4217Codes.put("ERN", "Eritrean nakfa"); 719 iso4217Codes.put("ETB", "Ethiopian birr"); 720 iso4217Codes.put("EUR", "Euro"); 721 iso4217Codes.put("FJD", "Fiji dollar"); 722 iso4217Codes.put("FKP", "Falkland Islands pound"); 723 iso4217Codes.put("GBP", "Pound sterling"); 724 iso4217Codes.put("GEL", "Georgian lari"); 725 iso4217Codes.put("GGP", "Guernsey Pound"); 726 iso4217Codes.put("GHS", "Ghanaian cedi"); 727 iso4217Codes.put("GIP", "Gibraltar pound"); 728 iso4217Codes.put("GMD", "Gambian dalasi"); 729 iso4217Codes.put("GNF", "Guinean franc"); 730 iso4217Codes.put("GTQ", "Guatemalan quetzal"); 731 iso4217Codes.put("GYD", "Guyanese dollar"); 732 iso4217Codes.put("HKD", "Hong Kong dollar"); 733 iso4217Codes.put("HNL", "Honduran lempira"); 734 iso4217Codes.put("HRK", "Croatian kuna"); 735 iso4217Codes.put("HTG", "Haitian gourde"); 736 iso4217Codes.put("HUF", "Hungarian forint"); 737 iso4217Codes.put("IDR", "Indonesian rupiah"); 738 iso4217Codes.put("ILS", "Israeli new shekel"); 739 iso4217Codes.put("IMP", "Isle of Man Pound"); 740 iso4217Codes.put("INR", "Indian rupee"); 741 iso4217Codes.put("IQD", "Iraqi dinar"); 742 iso4217Codes.put("IRR", "Iranian rial"); 743 iso4217Codes.put("ISK", "Icelandic króna"); 744 iso4217Codes.put("JEP", "Jersey Pound"); 745 iso4217Codes.put("JMD", "Jamaican dollar"); 746 iso4217Codes.put("JOD", "Jordanian dinar"); 747 iso4217Codes.put("JPY", "Japanese yen"); 748 iso4217Codes.put("KES", "Kenyan shilling"); 749 iso4217Codes.put("KGS", "Kyrgyzstani som"); 750 iso4217Codes.put("KHR", "Cambodian riel"); 751 iso4217Codes.put("KMF", "Comoro franc"); 752 iso4217Codes.put("KPW", "North Korean won"); 753 iso4217Codes.put("KRW", "South Korean won"); 754 iso4217Codes.put("KWD", "Kuwaiti dinar"); 755 iso4217Codes.put("KYD", "Cayman Islands dollar"); 756 iso4217Codes.put("KZT", "Kazakhstani tenge"); 757 iso4217Codes.put("LAK", "Lao kip"); 758 iso4217Codes.put("LBP", "Lebanese pound"); 759 iso4217Codes.put("LKR", "Sri Lankan rupee"); 760 iso4217Codes.put("LRD", "Liberian dollar"); 761 iso4217Codes.put("LSL", "Lesotho loti"); 762 iso4217Codes.put("LYD", "Libyan dinar"); 763 iso4217Codes.put("MAD", "Moroccan dirham"); 764 iso4217Codes.put("MDL", "Moldovan leu"); 765 iso4217Codes.put("MGA", "Malagasy ariary"); 766 iso4217Codes.put("MKD", "Macedonian denar"); 767 iso4217Codes.put("MMK", "Myanmar kyat"); 768 iso4217Codes.put("MNT", "Mongolian tögrög"); 769 iso4217Codes.put("MOP", "Macanese pataca"); 770 iso4217Codes.put("MRU", "Mauritanian ouguiya"); 771 iso4217Codes.put("MUR", "Mauritian rupee"); 772 iso4217Codes.put("MVR", "Maldivian rufiyaa"); 773 iso4217Codes.put("MWK", "Malawian kwacha"); 774 iso4217Codes.put("MXN", "Mexican peso"); 775 iso4217Codes.put("MXV", "Mexican Unidad de Inversion (UDI) (funds code)"); 776 iso4217Codes.put("MYR", "Malaysian ringgit"); 777 iso4217Codes.put("MZN", "Mozambican metical"); 778 iso4217Codes.put("NAD", "Namibian dollar"); 779 iso4217Codes.put("NGN", "Nigerian naira"); 780 iso4217Codes.put("NIO", "Nicaraguan córdoba"); 781 iso4217Codes.put("NOK", "Norwegian krone"); 782 iso4217Codes.put("NPR", "Nepalese rupee"); 783 iso4217Codes.put("NZD", "New Zealand dollar"); 784 iso4217Codes.put("OMR", "Omani rial"); 785 iso4217Codes.put("PAB", "Panamanian balboa"); 786 iso4217Codes.put("PEN", "Peruvian Sol"); 787 iso4217Codes.put("PGK", "Papua New Guinean kina"); 788 iso4217Codes.put("PHP", "Philippine piso[13]"); 789 iso4217Codes.put("PKR", "Pakistani rupee"); 790 iso4217Codes.put("PLN", "Polish z?oty"); 791 iso4217Codes.put("PYG", "Paraguayan guaraní"); 792 iso4217Codes.put("QAR", "Qatari riyal"); 793 iso4217Codes.put("RON", "Romanian leu"); 794 iso4217Codes.put("RSD", "Serbian dinar"); 795 iso4217Codes.put("RUB", "Russian ruble"); 796 iso4217Codes.put("RWF", "Rwandan franc"); 797 iso4217Codes.put("SAR", "Saudi riyal"); 798 iso4217Codes.put("SBD", "Solomon Islands dollar"); 799 iso4217Codes.put("SCR", "Seychelles rupee"); 800 iso4217Codes.put("SDG", "Sudanese pound"); 801 iso4217Codes.put("SEK", "Swedish krona/kronor"); 802 iso4217Codes.put("SGD", "Singapore dollar"); 803 iso4217Codes.put("SHP", "Saint Helena pound"); 804 iso4217Codes.put("SLL", "Sierra Leonean leone"); 805 iso4217Codes.put("SOS", "Somali shilling"); 806 iso4217Codes.put("SRD", "Surinamese dollar"); 807 iso4217Codes.put("SSP", "South Sudanese pound"); 808 iso4217Codes.put("STN", "São Tomé and Príncipe dobra"); 809 iso4217Codes.put("SVC", "Salvadoran colón"); 810 iso4217Codes.put("SYP", "Syrian pound"); 811 iso4217Codes.put("SZL", "Swazi lilangeni"); 812 iso4217Codes.put("THB", "Thai baht"); 813 iso4217Codes.put("TJS", "Tajikistani somoni"); 814 iso4217Codes.put("TMT", "Turkmenistan manat"); 815 iso4217Codes.put("TND", "Tunisian dinar"); 816 iso4217Codes.put("TOP", "Tongan pa?anga"); 817 iso4217Codes.put("TRY", "Turkish lira"); 818 iso4217Codes.put("TTD", "Trinidad and Tobago dollar"); 819 iso4217Codes.put("TVD", "Tuvalu Dollar"); 820 iso4217Codes.put("TWD", "New Taiwan dollar"); 821 iso4217Codes.put("TZS", "Tanzanian shilling"); 822 iso4217Codes.put("UAH", "Ukrainian hryvnia"); 823 iso4217Codes.put("UGX", "Ugandan shilling"); 824 iso4217Codes.put("USD", "United States dollar"); 825 iso4217Codes.put("USN", "United States dollar (next day) (funds code)"); 826 iso4217Codes.put("UYI", "Uruguay Peso en Unidades Indexadas (URUIURUI) (funds code)"); 827 iso4217Codes.put("UYU", "Uruguayan peso"); 828 iso4217Codes.put("UZS", "Uzbekistan som"); 829 iso4217Codes.put("VEF", "Venezuelan bolívar"); 830 iso4217Codes.put("VND", "Vietnamese ??ng"); 831 iso4217Codes.put("VUV", "Vanuatu vatu"); 832 iso4217Codes.put("WST", "Samoan tala"); 833 iso4217Codes.put("XAF", "CFA franc BEAC"); 834 iso4217Codes.put("XAG", "Silver (one troy ounce)"); 835 iso4217Codes.put("XAU", "Gold (one troy ounce)"); 836 iso4217Codes.put("XBA", "European Composite Unit (EURCO) (bond market unit)"); 837 iso4217Codes.put("XBB", "European Monetary Unit (E.M.U.-6) (bond market unit)"); 838 iso4217Codes.put("XBC", "European Unit of Account 9 (E.U.A.-9) (bond market unit)"); 839 iso4217Codes.put("XBD", "European Unit of Account 17 (E.U.A.-17) (bond market unit)"); 840 iso4217Codes.put("XCD", "East Caribbean dollar"); 841 iso4217Codes.put("XDR", "Special drawing rights"); 842 iso4217Codes.put("XOF", "CFA franc BCEAO"); 843 iso4217Codes.put("XPD", "Palladium (one troy ounce)"); 844 iso4217Codes.put("XPF", "CFP franc (franc Pacifique)"); 845 iso4217Codes.put("XPT", "Platinum (one troy ounce)"); 846 iso4217Codes.put("XSU", "SUCRE"); 847 iso4217Codes.put("XTS", "Code reserved for testing purposes"); 848 iso4217Codes.put("XUA", "ADB Unit of Account"); 849 iso4217Codes.put("XXX", "No currency"); 850 iso4217Codes.put("YER", "Yemeni rial"); 851 iso4217Codes.put("ZAR", "South African rand"); 852 iso4217Codes.put("ZMW", "Zambian kwacha"); 853 iso4217Codes.put("ZWL", "Zimbabwean dollar A/10"); 854 return iso4217Codes; 855 } 856 857 private static HashMap<String, String> buildIso3166Codes() { 858 HashMap<String, String> codes = new HashMap<>(); 859 860 // 2 letter codes 861 codes.put("AF", "Afghanistan"); 862 codes.put("AX", "Åland Islands"); 863 codes.put("AL", "Albania"); 864 codes.put("DZ", "Algeria"); 865 codes.put("AS", "American Samoa"); 866 codes.put("AD", "Andorra"); 867 codes.put("AO", "Angola"); 868 codes.put("AI", "Anguilla"); 869 codes.put("AQ", "Antarctica"); 870 codes.put("AG", "Antigua & Barbuda"); 871 codes.put("AR", "Argentina"); 872 codes.put("AM", "Armenia"); 873 codes.put("AW", "Aruba"); 874 codes.put("AU", "Australia"); 875 codes.put("AT", "Austria"); 876 codes.put("AZ", "Azerbaijan"); 877 codes.put("BS", "Bahamas"); 878 codes.put("BH", "Bahrain"); 879 codes.put("BD", "Bangladesh"); 880 codes.put("BB", "Barbados"); 881 codes.put("BY", "Belarus"); 882 codes.put("BE", "Belgium"); 883 codes.put("BZ", "Belize"); 884 codes.put("BJ", "Benin"); 885 codes.put("BM", "Bermuda"); 886 codes.put("BT", "Bhutan"); 887 codes.put("BO", "Bolivia"); 888 codes.put("BA", "Bosnia & Herzegovina"); 889 codes.put("BW", "Botswana"); 890 codes.put("BV", "Bouvet Island"); 891 codes.put("BR", "Brazil"); 892 codes.put("IO", "British Indian Ocean Territory"); 893 codes.put("VG", "British Virgin Islands"); 894 codes.put("BN", "Brunei"); 895 codes.put("BG", "Bulgaria"); 896 codes.put("BF", "Burkina Faso"); 897 codes.put("BI", "Burundi"); 898 codes.put("KH", "Cambodia"); 899 codes.put("CM", "Cameroon"); 900 codes.put("CA", "Canada"); 901 codes.put("CV", "Cape Verde"); 902 codes.put("BQ", "Caribbean Netherlands"); 903 codes.put("KY", "Cayman Islands"); 904 codes.put("CF", "Central African Republic"); 905 codes.put("TD", "Chad"); 906 codes.put("CL", "Chile"); 907 codes.put("CN", "China"); 908 codes.put("CX", "Christmas Island"); 909 codes.put("CC", "Cocos (Keeling) Islands"); 910 codes.put("CO", "Colombia"); 911 codes.put("KM", "Comoros"); 912 codes.put("CG", "Congo - Brazzaville"); 913 codes.put("CD", "Congo - Kinshasa"); 914 codes.put("CK", "Cook Islands"); 915 codes.put("CR", "Costa Rica"); 916 codes.put("CI", "Côte d?Ivoire"); 917 codes.put("HR", "Croatia"); 918 codes.put("CU", "Cuba"); 919 codes.put("CW", "Curaçao"); 920 codes.put("CY", "Cyprus"); 921 codes.put("CZ", "Czechia"); 922 codes.put("DK", "Denmark"); 923 codes.put("DJ", "Djibouti"); 924 codes.put("DM", "Dominica"); 925 codes.put("DO", "Dominican Republic"); 926 codes.put("EC", "Ecuador"); 927 codes.put("EG", "Egypt"); 928 codes.put("SV", "El Salvador"); 929 codes.put("GQ", "Equatorial Guinea"); 930 codes.put("ER", "Eritrea"); 931 codes.put("EE", "Estonia"); 932 codes.put("SZ", "Eswatini"); 933 codes.put("ET", "Ethiopia"); 934 codes.put("FK", "Falkland Islands"); 935 codes.put("FO", "Faroe Islands"); 936 codes.put("FJ", "Fiji"); 937 codes.put("FI", "Finland"); 938 codes.put("FR", "France"); 939 codes.put("GF", "French Guiana"); 940 codes.put("PF", "French Polynesia"); 941 codes.put("TF", "French Southern Territories"); 942 codes.put("GA", "Gabon"); 943 codes.put("GM", "Gambia"); 944 codes.put("GE", "Georgia"); 945 codes.put("DE", "Germany"); 946 codes.put("GH", "Ghana"); 947 codes.put("GI", "Gibraltar"); 948 codes.put("GR", "Greece"); 949 codes.put("GL", "Greenland"); 950 codes.put("GD", "Grenada"); 951 codes.put("GP", "Guadeloupe"); 952 codes.put("GU", "Guam"); 953 codes.put("GT", "Guatemala"); 954 codes.put("GG", "Guernsey"); 955 codes.put("GN", "Guinea"); 956 codes.put("GW", "Guinea-Bissau"); 957 codes.put("GY", "Guyana"); 958 codes.put("HT", "Haiti"); 959 codes.put("HM", "Heard & McDonald Islands"); 960 codes.put("HN", "Honduras"); 961 codes.put("HK", "Hong Kong SAR China"); 962 codes.put("HU", "Hungary"); 963 codes.put("IS", "Iceland"); 964 codes.put("IN", "India"); 965 codes.put("ID", "Indonesia"); 966 codes.put("IR", "Iran"); 967 codes.put("IQ", "Iraq"); 968 codes.put("IE", "Ireland"); 969 codes.put("IM", "Isle of Man"); 970 codes.put("IL", "Israel"); 971 codes.put("IT", "Italy"); 972 codes.put("JM", "Jamaica"); 973 codes.put("JP", "Japan"); 974 codes.put("JE", "Jersey"); 975 codes.put("JO", "Jordan"); 976 codes.put("KZ", "Kazakhstan"); 977 codes.put("KE", "Kenya"); 978 codes.put("KI", "Kiribati"); 979 codes.put("KW", "Kuwait"); 980 codes.put("KG", "Kyrgyzstan"); 981 codes.put("LA", "Laos"); 982 codes.put("LV", "Latvia"); 983 codes.put("LB", "Lebanon"); 984 codes.put("LS", "Lesotho"); 985 codes.put("LR", "Liberia"); 986 codes.put("LY", "Libya"); 987 codes.put("LI", "Liechtenstein"); 988 codes.put("LT", "Lithuania"); 989 codes.put("LU", "Luxembourg"); 990 codes.put("MO", "Macao SAR China"); 991 codes.put("MG", "Madagascar"); 992 codes.put("MW", "Malawi"); 993 codes.put("MY", "Malaysia"); 994 codes.put("MV", "Maldives"); 995 codes.put("ML", "Mali"); 996 codes.put("MT", "Malta"); 997 codes.put("MH", "Marshall Islands"); 998 codes.put("MQ", "Martinique"); 999 codes.put("MR", "Mauritania"); 1000 codes.put("MU", "Mauritius"); 1001 codes.put("YT", "Mayotte"); 1002 codes.put("MX", "Mexico"); 1003 codes.put("FM", "Micronesia"); 1004 codes.put("MD", "Moldova"); 1005 codes.put("MC", "Monaco"); 1006 codes.put("MN", "Mongolia"); 1007 codes.put("ME", "Montenegro"); 1008 codes.put("MS", "Montserrat"); 1009 codes.put("MA", "Morocco"); 1010 codes.put("MZ", "Mozambique"); 1011 codes.put("MM", "Myanmar (Burma)"); 1012 codes.put("NA", "Namibia"); 1013 codes.put("NR", "Nauru"); 1014 codes.put("NP", "Nepal"); 1015 codes.put("NL", "Netherlands"); 1016 codes.put("NC", "New Caledonia"); 1017 codes.put("NZ", "New Zealand"); 1018 codes.put("NI", "Nicaragua"); 1019 codes.put("NE", "Niger"); 1020 codes.put("NG", "Nigeria"); 1021 codes.put("NU", "Niue"); 1022 codes.put("NF", "Norfolk Island"); 1023 codes.put("KP", "North Korea"); 1024 codes.put("MK", "North Macedonia"); 1025 codes.put("MP", "Northern Mariana Islands"); 1026 codes.put("NO", "Norway"); 1027 codes.put("OM", "Oman"); 1028 codes.put("PK", "Pakistan"); 1029 codes.put("PW", "Palau"); 1030 codes.put("PS", "Palestinian Territories"); 1031 codes.put("PA", "Panama"); 1032 codes.put("PG", "Papua New Guinea"); 1033 codes.put("PY", "Paraguay"); 1034 codes.put("PE", "Peru"); 1035 codes.put("PH", "Philippines"); 1036 codes.put("PN", "Pitcairn Islands"); 1037 codes.put("PL", "Poland"); 1038 codes.put("PT", "Portugal"); 1039 codes.put("PR", "Puerto Rico"); 1040 codes.put("QA", "Qatar"); 1041 codes.put("RE", "Réunion"); 1042 codes.put("RO", "Romania"); 1043 codes.put("RU", "Russia"); 1044 codes.put("RW", "Rwanda"); 1045 codes.put("WS", "Samoa"); 1046 codes.put("SM", "San Marino"); 1047 codes.put("ST", "São Tomé & Príncipe"); 1048 codes.put("SA", "Saudi Arabia"); 1049 codes.put("SN", "Senegal"); 1050 codes.put("RS", "Serbia"); 1051 codes.put("SC", "Seychelles"); 1052 codes.put("SL", "Sierra Leone"); 1053 codes.put("SG", "Singapore"); 1054 codes.put("SX", "Sint Maarten"); 1055 codes.put("SK", "Slovakia"); 1056 codes.put("SI", "Slovenia"); 1057 codes.put("SB", "Solomon Islands"); 1058 codes.put("SO", "Somalia"); 1059 codes.put("ZA", "South Africa"); 1060 codes.put("GS", "South Georgia & South Sandwich Islands"); 1061 codes.put("KR", "South Korea"); 1062 codes.put("SS", "South Sudan"); 1063 codes.put("ES", "Spain"); 1064 codes.put("LK", "Sri Lanka"); 1065 codes.put("BL", "St. Barthélemy"); 1066 codes.put("SH", "St. Helena"); 1067 codes.put("KN", "St. Kitts & Nevis"); 1068 codes.put("LC", "St. Lucia"); 1069 codes.put("MF", "St. Martin"); 1070 codes.put("PM", "St. Pierre & Miquelon"); 1071 codes.put("VC", "St. Vincent & Grenadines"); 1072 codes.put("SD", "Sudan"); 1073 codes.put("SR", "Suriname"); 1074 codes.put("SJ", "Svalbard & Jan Mayen"); 1075 codes.put("SE", "Sweden"); 1076 codes.put("CH", "Switzerland"); 1077 codes.put("SY", "Syria"); 1078 codes.put("TW", "Taiwan"); 1079 codes.put("TJ", "Tajikistan"); 1080 codes.put("TZ", "Tanzania"); 1081 codes.put("TH", "Thailand"); 1082 codes.put("TL", "Timor-Leste"); 1083 codes.put("TG", "Togo"); 1084 codes.put("TK", "Tokelau"); 1085 codes.put("TO", "Tonga"); 1086 codes.put("TT", "Trinidad & Tobago"); 1087 codes.put("TN", "Tunisia"); 1088 codes.put("TR", "Turkey"); 1089 codes.put("TM", "Turkmenistan"); 1090 codes.put("TC", "Turks & Caicos Islands"); 1091 codes.put("TV", "Tuvalu"); 1092 codes.put("UM", "U.S. Outlying Islands"); 1093 codes.put("VI", "U.S. Virgin Islands"); 1094 codes.put("UG", "Uganda"); 1095 codes.put("UA", "Ukraine"); 1096 codes.put("AE", "United Arab Emirates"); 1097 codes.put("GB", "United Kingdom"); 1098 codes.put("US", "United States"); 1099 codes.put("UY", "Uruguay"); 1100 codes.put("UZ", "Uzbekistan"); 1101 codes.put("VU", "Vanuatu"); 1102 codes.put("VA", "Vatican City"); 1103 codes.put("VE", "Venezuela"); 1104 codes.put("VN", "Vietnam"); 1105 codes.put("WF", "Wallis & Futuna"); 1106 codes.put("EH", "Western Sahara"); 1107 codes.put("YE", "Yemen"); 1108 codes.put("ZM", "Zambia"); 1109 codes.put("ZW", "Zimbabwe"); 1110 1111 // 3 letter codes 1112 codes.put("ABW", "Aruba"); 1113 codes.put("AFG", "Afghanistan"); 1114 codes.put("AGO", "Angola"); 1115 codes.put("AIA", "Anguilla"); 1116 codes.put("ALA", "Åland Islands"); 1117 codes.put("ALB", "Albania"); 1118 codes.put("AND", "Andorra"); 1119 codes.put("ARE", "United Arab Emirates"); 1120 codes.put("ARG", "Argentina"); 1121 codes.put("ARM", "Armenia"); 1122 codes.put("ASM", "American Samoa"); 1123 codes.put("ATA", "Antarctica"); 1124 codes.put("ATF", "French Southern Territories"); 1125 codes.put("ATG", "Antigua and Barbuda"); 1126 codes.put("AUS", "Australia"); 1127 codes.put("AUT", "Austria"); 1128 codes.put("AZE", "Azerbaijan"); 1129 codes.put("BDI", "Burundi"); 1130 codes.put("BEL", "Belgium"); 1131 codes.put("BEN", "Benin"); 1132 codes.put("BES", "Bonaire, Sint Eustatius and Saba"); 1133 codes.put("BFA", "Burkina Faso"); 1134 codes.put("BGD", "Bangladesh"); 1135 codes.put("BGR", "Bulgaria"); 1136 codes.put("BHR", "Bahrain"); 1137 codes.put("BHS", "Bahamas"); 1138 codes.put("BIH", "Bosnia and Herzegovina"); 1139 codes.put("BLM", "Saint Barthélemy"); 1140 codes.put("BLR", "Belarus"); 1141 codes.put("BLZ", "Belize"); 1142 codes.put("BMU", "Bermuda"); 1143 codes.put("BOL", "Bolivia, Plurinational State of"); 1144 codes.put("BRA", "Brazil"); 1145 codes.put("BRB", "Barbados"); 1146 codes.put("BRN", "Brunei Darussalam"); 1147 codes.put("BTN", "Bhutan"); 1148 codes.put("BVT", "Bouvet Island"); 1149 codes.put("BWA", "Botswana"); 1150 codes.put("CAF", "Central African Republic"); 1151 codes.put("CAN", "Canada"); 1152 codes.put("CCK", "Cocos (Keeling) Islands"); 1153 codes.put("CHE", "Switzerland"); 1154 codes.put("CHL", "Chile"); 1155 codes.put("CHN", "China"); 1156 codes.put("CIV", "Côte d'Ivoire"); 1157 codes.put("CMR", "Cameroon"); 1158 codes.put("COD", "Congo, the Democratic Republic of the"); 1159 codes.put("COG", "Congo"); 1160 codes.put("COK", "Cook Islands"); 1161 codes.put("COL", "Colombia"); 1162 codes.put("COM", "Comoros"); 1163 codes.put("CPV", "Cabo Verde"); 1164 codes.put("CRI", "Costa Rica"); 1165 codes.put("CUB", "Cuba"); 1166 codes.put("CUW", "Curaçao"); 1167 codes.put("CXR", "Christmas Island"); 1168 codes.put("CYM", "Cayman Islands"); 1169 codes.put("CYP", "Cyprus"); 1170 codes.put("CZE", "Czechia"); 1171 codes.put("DEU", "Germany"); 1172 codes.put("DJI", "Djibouti"); 1173 codes.put("DMA", "Dominica"); 1174 codes.put("DNK", "Denmark"); 1175 codes.put("DOM", "Dominican Republic"); 1176 codes.put("DZA", "Algeria"); 1177 codes.put("ECU", "Ecuador"); 1178 codes.put("EGY", "Egypt"); 1179 codes.put("ERI", "Eritrea"); 1180 codes.put("ESH", "Western Sahara"); 1181 codes.put("ESP", "Spain"); 1182 codes.put("EST", "Estonia"); 1183 codes.put("ETH", "Ethiopia"); 1184 codes.put("FIN", "Finland"); 1185 codes.put("FJI", "Fiji"); 1186 codes.put("FLK", "Falkland Islands (Malvinas)"); 1187 codes.put("FRA", "France"); 1188 codes.put("FRO", "Faroe Islands"); 1189 codes.put("FSM", "Micronesia, Federated States of"); 1190 codes.put("GAB", "Gabon"); 1191 codes.put("GBR", "United Kingdom"); 1192 codes.put("GEO", "Georgia"); 1193 codes.put("GGY", "Guernsey"); 1194 codes.put("GHA", "Ghana"); 1195 codes.put("GIB", "Gibraltar"); 1196 codes.put("GIN", "Guinea"); 1197 codes.put("GLP", "Guadeloupe"); 1198 codes.put("GMB", "Gambia"); 1199 codes.put("GNB", "Guinea-Bissau"); 1200 codes.put("GNQ", "Equatorial Guinea"); 1201 codes.put("GRC", "Greece"); 1202 codes.put("GRD", "Grenada"); 1203 codes.put("GRL", "Greenland"); 1204 codes.put("GTM", "Guatemala"); 1205 codes.put("GUF", "French Guiana"); 1206 codes.put("GUM", "Guam"); 1207 codes.put("GUY", "Guyana"); 1208 codes.put("HKG", "Hong Kong"); 1209 codes.put("HMD", "Heard Island and McDonald Islands"); 1210 codes.put("HND", "Honduras"); 1211 codes.put("HRV", "Croatia"); 1212 codes.put("HTI", "Haiti"); 1213 codes.put("HUN", "Hungary"); 1214 codes.put("IDN", "Indonesia"); 1215 codes.put("IMN", "Isle of Man"); 1216 codes.put("IND", "India"); 1217 codes.put("IOT", "British Indian Ocean Territory"); 1218 codes.put("IRL", "Ireland"); 1219 codes.put("IRN", "Iran, Islamic Republic of"); 1220 codes.put("IRQ", "Iraq"); 1221 codes.put("ISL", "Iceland"); 1222 codes.put("ISR", "Israel"); 1223 codes.put("ITA", "Italy"); 1224 codes.put("JAM", "Jamaica"); 1225 codes.put("JEY", "Jersey"); 1226 codes.put("JOR", "Jordan"); 1227 codes.put("JPN", "Japan"); 1228 codes.put("KAZ", "Kazakhstan"); 1229 codes.put("KEN", "Kenya"); 1230 codes.put("KGZ", "Kyrgyzstan"); 1231 codes.put("KHM", "Cambodia"); 1232 codes.put("KIR", "Kiribati"); 1233 codes.put("KNA", "Saint Kitts and Nevis"); 1234 codes.put("KOR", "Korea, Republic of"); 1235 codes.put("KWT", "Kuwait"); 1236 codes.put("LAO", "Lao People's Democratic Republic"); 1237 codes.put("LBN", "Lebanon"); 1238 codes.put("LBR", "Liberia"); 1239 codes.put("LBY", "Libya"); 1240 codes.put("LCA", "Saint Lucia"); 1241 codes.put("LIE", "Liechtenstein"); 1242 codes.put("LKA", "Sri Lanka"); 1243 codes.put("LSO", "Lesotho"); 1244 codes.put("LTU", "Lithuania"); 1245 codes.put("LUX", "Luxembourg"); 1246 codes.put("LVA", "Latvia"); 1247 codes.put("MAC", "Macao"); 1248 codes.put("MAF", "Saint Martin (French part)"); 1249 codes.put("MAR", "Morocco"); 1250 codes.put("MCO", "Monaco"); 1251 codes.put("MDA", "Moldova, Republic of"); 1252 codes.put("MDG", "Madagascar"); 1253 codes.put("MDV", "Maldives"); 1254 codes.put("MEX", "Mexico"); 1255 codes.put("MHL", "Marshall Islands"); 1256 codes.put("MKD", "Macedonia, the former Yugoslav Republic of"); 1257 codes.put("MLI", "Mali"); 1258 codes.put("MLT", "Malta"); 1259 codes.put("MMR", "Myanmar"); 1260 codes.put("MNE", "Montenegro"); 1261 codes.put("MNG", "Mongolia"); 1262 codes.put("MNP", "Northern Mariana Islands"); 1263 codes.put("MOZ", "Mozambique"); 1264 codes.put("MRT", "Mauritania"); 1265 codes.put("MSR", "Montserrat"); 1266 codes.put("MTQ", "Martinique"); 1267 codes.put("MUS", "Mauritius"); 1268 codes.put("MWI", "Malawi"); 1269 codes.put("MYS", "Malaysia"); 1270 codes.put("MYT", "Mayotte"); 1271 codes.put("NAM", "Namibia"); 1272 codes.put("NCL", "New Caledonia"); 1273 codes.put("NER", "Niger"); 1274 codes.put("NFK", "Norfolk Island"); 1275 codes.put("NGA", "Nigeria"); 1276 codes.put("NIC", "Nicaragua"); 1277 codes.put("NIU", "Niue"); 1278 codes.put("NLD", "Netherlands"); 1279 codes.put("NOR", "Norway"); 1280 codes.put("NPL", "Nepal"); 1281 codes.put("NRU", "Nauru"); 1282 codes.put("NZL", "New Zealand"); 1283 codes.put("OMN", "Oman"); 1284 codes.put("PAK", "Pakistan"); 1285 codes.put("PAN", "Panama"); 1286 codes.put("PCN", "Pitcairn"); 1287 codes.put("PER", "Peru"); 1288 codes.put("PHL", "Philippines"); 1289 codes.put("PLW", "Palau"); 1290 codes.put("PNG", "Papua New Guinea"); 1291 codes.put("POL", "Poland"); 1292 codes.put("PRI", "Puerto Rico"); 1293 codes.put("PRK", "Korea, Democratic People's Republic of"); 1294 codes.put("PRT", "Portugal"); 1295 codes.put("PRY", "Paraguay"); 1296 codes.put("PSE", "Palestine, State of"); 1297 codes.put("PYF", "French Polynesia"); 1298 codes.put("QAT", "Qatar"); 1299 codes.put("REU", "Réunion"); 1300 codes.put("ROU", "Romania"); 1301 codes.put("RUS", "Russian Federation"); 1302 codes.put("RWA", "Rwanda"); 1303 codes.put("SAU", "Saudi Arabia"); 1304 codes.put("SDN", "Sudan"); 1305 codes.put("SEN", "Senegal"); 1306 codes.put("SGP", "Singapore"); 1307 codes.put("SGS", "South Georgia and the South Sandwich Islands"); 1308 codes.put("SHN", "Saint Helena, Ascension and Tristan da Cunha"); 1309 codes.put("SJM", "Svalbard and Jan Mayen"); 1310 codes.put("SLB", "Solomon Islands"); 1311 codes.put("SLE", "Sierra Leone"); 1312 codes.put("SLV", "El Salvador"); 1313 codes.put("SMR", "San Marino"); 1314 codes.put("SOM", "Somalia"); 1315 codes.put("SPM", "Saint Pierre and Miquelon"); 1316 codes.put("SRB", "Serbia"); 1317 codes.put("SSD", "South Sudan"); 1318 codes.put("STP", "Sao Tome and Principe"); 1319 codes.put("SUR", "Suriname"); 1320 codes.put("SVK", "Slovakia"); 1321 codes.put("SVN", "Slovenia"); 1322 codes.put("SWE", "Sweden"); 1323 codes.put("SWZ", "Swaziland"); 1324 codes.put("SXM", "Sint Maarten (Dutch part)"); 1325 codes.put("SYC", "Seychelles"); 1326 codes.put("SYR", "Syrian Arab Republic"); 1327 codes.put("TCA", "Turks and Caicos Islands"); 1328 codes.put("TCD", "Chad"); 1329 codes.put("TGO", "Togo"); 1330 codes.put("THA", "Thailand"); 1331 codes.put("TJK", "Tajikistan"); 1332 codes.put("TKL", "Tokelau"); 1333 codes.put("TKM", "Turkmenistan"); 1334 codes.put("TLS", "Timor-Leste"); 1335 codes.put("TON", "Tonga"); 1336 codes.put("TTO", "Trinidad and Tobago"); 1337 codes.put("TUN", "Tunisia"); 1338 codes.put("TUR", "Turkey"); 1339 codes.put("TUV", "Tuvalu"); 1340 codes.put("TWN", "Taiwan, Province of China"); 1341 codes.put("TZA", "Tanzania, United Republic of"); 1342 codes.put("UGA", "Uganda"); 1343 codes.put("UKR", "Ukraine"); 1344 codes.put("UMI", "United States Minor Outlying Islands"); 1345 codes.put("URY", "Uruguay"); 1346 codes.put("USA", "United States of America"); 1347 codes.put("UZB", "Uzbekistan"); 1348 codes.put("VAT", "Holy See"); 1349 codes.put("VCT", "Saint Vincent and the Grenadines"); 1350 codes.put("VEN", "Venezuela, Bolivarian Republic of"); 1351 codes.put("VGB", "Virgin Islands, British"); 1352 codes.put("VIR", "Virgin Islands, U.S."); 1353 codes.put("VNM", "Viet Nam"); 1354 codes.put("VUT", "Vanuatu"); 1355 codes.put("WLF", "Wallis and Futuna"); 1356 codes.put("WSM", "Samoa"); 1357 codes.put("YEM", "Yemen"); 1358 codes.put("ZAF", "South Africa"); 1359 codes.put("ZMB", "Zambia"); 1360 codes.put("ZWE", "Zimbabwe"); 1361 return codes; 1362 } 1363 1364 protected String getErrorMessage(String errorCode, String theFirstParam, String theSecondParam) { 1365 return myFhirContext.getLocalizer().getMessage(getClass(), errorCode, theFirstParam, theSecondParam); 1366 } 1367}