Merge pull request #2921 from hapifhir/issue-2920-lookup-lang-by-lang-only
Fix language lookup bug when omitting region during $validate
This commit is contained in:
commit
3a7d778591
|
@ -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`"
|
|
@ -104,7 +104,6 @@ import org.hl7.fhir.r4.model.Organization;
|
|||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Period;
|
||||
import org.hl7.fhir.r4.model.Practitioner;
|
||||
import org.hl7.fhir.r4.model.Procedure;
|
||||
import org.hl7.fhir.r4.model.Provenance;
|
||||
import org.hl7.fhir.r4.model.Quantity;
|
||||
import org.hl7.fhir.r4.model.Questionnaire;
|
||||
|
@ -5304,7 +5303,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
|||
createObservationWithEffective("YES22", "2011-01-02T00:00:00+10:00");
|
||||
createObservationWithEffective("YES23", "2011-01-02T00:00:00+11:00");
|
||||
|
||||
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.setLoadSynchronous(true);
|
||||
map.add(Observation.SP_DATE, new DateParam("2011-01-02"));
|
||||
|
|
|
@ -257,69 +257,100 @@ public class CommonCodeSystemsTerminologyService implements IValidationSupport {
|
|||
Map<String, String> languagesMap = myLanguagesLanugageMap;
|
||||
Map<String, String> regionsMap = myLanguagesRegionMap;
|
||||
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");
|
||||
ArrayNode map;
|
||||
try {
|
||||
map = (ArrayNode) new ObjectMapper().readTree(input);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new ConfigurationException(e);
|
||||
if (hasRegionAndCodeSegments) {
|
||||
language = myLanguagesLanugageMap.get(theCode.substring(0, langRegionSeparatorIndex));
|
||||
region = myLanguagesRegionMap.get(theCode.substring(langRegionSeparatorIndex + 1));
|
||||
|
||||
if (language == null || region == null) {
|
||||
//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);
|
||||
}
|
||||
|
||||
languagesMap = new HashMap<>();
|
||||
regionsMap = new HashMap<>();
|
||||
|
||||
for (int i = 0; i < map.size(); i++) {
|
||||
ObjectNode next = (ObjectNode) map.get(i);
|
||||
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);
|
||||
}
|
||||
|
||||
} else {
|
||||
//In case user has only provided a language, we build the lookup from only that.
|
||||
language = myLanguagesLanugageMap.get(theCode);
|
||||
if (language == null) {
|
||||
ourLog.warn("Couldn't find a valid bcp47 language from code: {}", theCode);
|
||||
return buildNotFoundLookupCodeResult(theCode);
|
||||
} else {
|
||||
return buildLookupResultForLanguage(theCode, language);
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
myLanguagesRegionMap = regionsMap;
|
||||
private void initializeBcp47LanguageMap() {
|
||||
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, '-', '_');
|
||||
String language = null;
|
||||
String region = null;
|
||||
if (idx > 0) {
|
||||
language = languagesMap.get(theCode.substring(0, idx));
|
||||
region = regionsMap.get(theCode.substring(idx + 1));
|
||||
languagesMap = new HashMap<>();
|
||||
regionsMap = new HashMap<>();
|
||||
|
||||
for (int i = 0; i < map.size(); i++) {
|
||||
ObjectNode next = (ObjectNode) map.get(i);
|
||||
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();
|
||||
retVal.setSearchedForCode(theCode);
|
||||
retVal.setSearchedForSystem(LANGUAGES_CODESYSTEM_URL);
|
||||
ourLog.info("Have {} languages and {} regions", languagesMap.size(), regionsMap.size());
|
||||
|
||||
if (language != null && region != null) {
|
||||
String display = language + " " + region;
|
||||
retVal.setFound(true);
|
||||
retVal.setCodeDisplay(display);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
myLanguagesLanugageMap = languagesMap;
|
||||
myLanguagesRegionMap = regionsMap;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
|
|
@ -105,6 +105,20 @@ public class CommonCodeSystemsTerminologyServiceTest {
|
|||
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
|
||||
public void testLanguages_CommonLanguagesVs_LanguageAndRegion() {
|
||||
IValidationSupport.LookupCodeResult nl = mySvc.lookupCode(newSupport(), "urn:ietf:bcp:47", "nl-NL");
|
||||
assertTrue(nl.isFound());
|
||||
assertEquals("Dutch Netherlands", nl.getCodeDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLanguages_CommonLanguagesVs_BadCode() {
|
||||
IValidationSupport.CodeValidationResult outcome = mySvc.validateCode(newSupport(), newOptions(), "urn:ietf:bcp:47", "FOO", null, "http://hl7.org/fhir/ValueSet/languages");
|
||||
|
|
Loading…
Reference in New Issue