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