Fix bug in code. Add test. Add changelog
This commit is contained in:
parent
090a8b0821
commit
fd6dcf6363
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 2920
|
||||||
|
jira: SMILE-2971
|
||||||
|
title: "Previously, validation against bcp47 (urn:ietf:bcp:47) as a language would fail validation if the region was absent. This has been fixed, and the validate
|
||||||
|
operation will now correctly validate simple languages, e.g. `nl` instead of requiring `nl-DE` or `nl-NL`"
|
|
@ -257,69 +257,100 @@ public class CommonCodeSystemsTerminologyService implements IValidationSupport {
|
||||||
Map<String, String> languagesMap = myLanguagesLanugageMap;
|
Map<String, String> languagesMap = myLanguagesLanugageMap;
|
||||||
Map<String, String> regionsMap = myLanguagesRegionMap;
|
Map<String, String> regionsMap = myLanguagesRegionMap;
|
||||||
if (languagesMap == null || regionsMap == null) {
|
if (languagesMap == null || regionsMap == null) {
|
||||||
|
initializeBcp47LanguageMap();
|
||||||
|
}
|
||||||
|
|
||||||
ourLog.info("Loading BCP47 Language Registry");
|
int langRegionSeparatorIndex = StringUtils.indexOfAny(theCode, '-', '_');
|
||||||
|
boolean hasRegionAndCodeSegments = langRegionSeparatorIndex > 0;
|
||||||
|
String language;
|
||||||
|
String region;
|
||||||
|
|
||||||
String input = ClasspathUtil.loadResource("org/hl7/fhir/common/hapi/validation/support/registry.json");
|
if (hasRegionAndCodeSegments) {
|
||||||
ArrayNode map;
|
language = myLanguagesLanugageMap.get(theCode.substring(0, langRegionSeparatorIndex));
|
||||||
try {
|
region = myLanguagesRegionMap.get(theCode.substring(langRegionSeparatorIndex + 1));
|
||||||
map = (ArrayNode) new ObjectMapper().readTree(input);
|
|
||||||
} catch (JsonProcessingException e) {
|
if (language == null || region == null) {
|
||||||
throw new ConfigurationException(e);
|
//In case the user provides both a language and a region, they must both be valid for the lookup to succeed.
|
||||||
|
ourLog.warn("Couldn't find a valid bcp47 language-region combination from code: {}", theCode);
|
||||||
|
return buildNotFoundLookupCodeResult(theCode);
|
||||||
|
} else {
|
||||||
|
return buildLookupResultForLanguageAndRegion(theCode, language, region);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
languagesMap = new HashMap<>();
|
//In case user has only provided a language, we build the lookup from only that.
|
||||||
regionsMap = new HashMap<>();
|
language = myLanguagesLanugageMap.get(theCode);
|
||||||
|
if (language == null) {
|
||||||
for (int i = 0; i < map.size(); i++) {
|
ourLog.warn("Couldn't find a valid bcp47 language from code: {}", theCode);
|
||||||
ObjectNode next = (ObjectNode) map.get(i);
|
return buildNotFoundLookupCodeResult(theCode);
|
||||||
String type = next.get("Type").asText();
|
} else {
|
||||||
if ("language".equals(type)) {
|
return buildLookupResultForLanguage(theCode, language);
|
||||||
String language = next.get("Subtag").asText();
|
|
||||||
ArrayNode descriptions = (ArrayNode) next.get("Description");
|
|
||||||
String description = null;
|
|
||||||
if (descriptions.size() > 0) {
|
|
||||||
description = descriptions.get(0).asText();
|
|
||||||
}
|
|
||||||
languagesMap.put(language, description);
|
|
||||||
}
|
|
||||||
if ("region".equals(type)) {
|
|
||||||
String region = next.get("Subtag").asText();
|
|
||||||
ArrayNode descriptions = (ArrayNode) next.get("Description");
|
|
||||||
String description = null;
|
|
||||||
if (descriptions.size() > 0) {
|
|
||||||
description = descriptions.get(0).asText();
|
|
||||||
}
|
|
||||||
regionsMap.put(region, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private LookupCodeResult buildLookupResultForLanguageAndRegion(@Nonnull String theOriginalCode, @Nonnull String theLanguage, @Nonnull String theRegion) {
|
||||||
|
LookupCodeResult lookupCodeResult = buildNotFoundLookupCodeResult(theOriginalCode);
|
||||||
|
lookupCodeResult.setCodeDisplay(theLanguage + " " + theRegion);
|
||||||
|
lookupCodeResult.setFound(true);
|
||||||
|
return lookupCodeResult;
|
||||||
|
}
|
||||||
|
private LookupCodeResult buildLookupResultForLanguage(@Nonnull String theOriginalCode, @Nonnull String theLanguage) {
|
||||||
|
LookupCodeResult lookupCodeResult = buildNotFoundLookupCodeResult(theOriginalCode);
|
||||||
|
lookupCodeResult.setCodeDisplay(theLanguage);
|
||||||
|
lookupCodeResult.setFound(true);
|
||||||
|
return lookupCodeResult;
|
||||||
|
}
|
||||||
|
|
||||||
ourLog.info("Have {} languages and {} regions", languagesMap.size(), regionsMap.size());
|
private LookupCodeResult buildNotFoundLookupCodeResult(@Nonnull String theOriginalCode) {
|
||||||
|
LookupCodeResult lookupCodeResult = new LookupCodeResult();
|
||||||
|
lookupCodeResult.setFound(false);
|
||||||
|
lookupCodeResult.setSearchedForSystem(LANGUAGES_CODESYSTEM_URL);
|
||||||
|
lookupCodeResult.setSearchedForCode(theOriginalCode);
|
||||||
|
return lookupCodeResult;
|
||||||
|
}
|
||||||
|
|
||||||
myLanguagesLanugageMap = languagesMap;
|
private void initializeBcp47LanguageMap() {
|
||||||
myLanguagesRegionMap = regionsMap;
|
Map<String, String> regionsMap;
|
||||||
|
Map<String, String> languagesMap;
|
||||||
|
ourLog.info("Loading BCP47 Language Registry");
|
||||||
|
|
||||||
|
String input = ClasspathUtil.loadResource("org/hl7/fhir/common/hapi/validation/support/registry.json");
|
||||||
|
ArrayNode map;
|
||||||
|
try {
|
||||||
|
map = (ArrayNode) new ObjectMapper().readTree(input);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new ConfigurationException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = StringUtils.indexOfAny(theCode, '-', '_');
|
languagesMap = new HashMap<>();
|
||||||
String language = null;
|
regionsMap = new HashMap<>();
|
||||||
String region = null;
|
|
||||||
if (idx > 0) {
|
for (int i = 0; i < map.size(); i++) {
|
||||||
language = languagesMap.get(theCode.substring(0, idx));
|
ObjectNode next = (ObjectNode) map.get(i);
|
||||||
region = regionsMap.get(theCode.substring(idx + 1));
|
String type = next.get("Type").asText();
|
||||||
|
if ("language".equals(type)) {
|
||||||
|
String language = next.get("Subtag").asText();
|
||||||
|
ArrayNode descriptions = (ArrayNode) next.get("Description");
|
||||||
|
String description = null;
|
||||||
|
if (descriptions.size() > 0) {
|
||||||
|
description = descriptions.get(0).asText();
|
||||||
|
}
|
||||||
|
languagesMap.put(language, description);
|
||||||
|
}
|
||||||
|
if ("region".equals(type)) {
|
||||||
|
String region = next.get("Subtag").asText();
|
||||||
|
ArrayNode descriptions = (ArrayNode) next.get("Description");
|
||||||
|
String description = null;
|
||||||
|
if (descriptions.size() > 0) {
|
||||||
|
description = descriptions.get(0).asText();
|
||||||
|
}
|
||||||
|
regionsMap.put(region, description);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LookupCodeResult retVal = new LookupCodeResult();
|
ourLog.info("Have {} languages and {} regions", languagesMap.size(), regionsMap.size());
|
||||||
retVal.setSearchedForCode(theCode);
|
|
||||||
retVal.setSearchedForSystem(LANGUAGES_CODESYSTEM_URL);
|
|
||||||
|
|
||||||
if (language != null && region != null) {
|
myLanguagesLanugageMap = languagesMap;
|
||||||
String display = language + " " + region;
|
myLanguagesRegionMap = regionsMap;
|
||||||
retVal.setFound(true);
|
|
||||||
retVal.setCodeDisplay(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
|
|
@ -105,6 +105,13 @@ public class CommonCodeSystemsTerminologyServiceTest {
|
||||||
assertEquals("English (United States)", outcome.getDisplay());
|
assertEquals("English (United States)", outcome.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLanguages_CommonLanguagesVs_OnlyLanguage_NoRegion() {
|
||||||
|
IValidationSupport.LookupCodeResult nl = mySvc.lookupCode(newSupport(), "urn:ietf:bcp:47", "nl");
|
||||||
|
assertTrue(nl.isFound());
|
||||||
|
assertEquals("Dutch", nl.getCodeDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLanguages_CommonLanguagesVs_BadCode() {
|
public void testLanguages_CommonLanguagesVs_BadCode() {
|
||||||
IValidationSupport.CodeValidationResult outcome = mySvc.validateCode(newSupport(), newOptions(), "urn:ietf:bcp:47", "FOO", null, "http://hl7.org/fhir/ValueSet/languages");
|
IValidationSupport.CodeValidationResult outcome = mySvc.validateCode(newSupport(), newOptions(), "urn:ietf:bcp:47", "FOO", null, "http://hl7.org/fhir/ValueSet/languages");
|
||||||
|
|
Loading…
Reference in New Issue