Skip to content

Commit

Permalink
OCLOMRS-1086: Concept Sources should match based on normalized names (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mseaton authored Feb 9, 2022
1 parent fa9591e commit 2324aac
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
*/
package org.openmrs.module.openconceptlab;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.openmrs.Concept;
import org.openmrs.ConceptClass;
import org.openmrs.ConceptDatatype;
Expand All @@ -20,6 +17,11 @@
import org.openmrs.ConceptSource;
import org.openmrs.api.ConceptService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CacheService {

ConceptService conceptService;
Expand Down Expand Up @@ -78,16 +80,38 @@ public ConceptClass getConceptClassByName(String name) {
}
}

/**
* If a concept name exists with an exact matching name (case-insensitive), then return it
* Else, do a normalized comparison, ignoring spaces, dashes, and underscores. If exactly one match is found,
* then return it. If more than one match is found, throw an Exception.
*/
public ConceptSource getConceptSourceByName(String name) {
ConceptSource conceptSource = conceptSources.get(name);
if (conceptSource != null) {
return conceptSource;
} else {
conceptSource = conceptService.getConceptSourceByName(name);
if (conceptSource != null) {
conceptSources.put(name, conceptSource);
String normalizedName = Utils.normalizeConceptSourceName(name);
ConceptSource match = null;
List<ConceptSource> fuzzyMatches = new ArrayList<>();
for (ConceptSource possibleMatch : conceptService.getAllConceptSources(true)) {
if (possibleMatch.getName().equalsIgnoreCase(name)) {
match = possibleMatch;
}
else if (Utils.normalizeConceptSourceName(possibleMatch.getName()).equals(normalizedName)) {
fuzzyMatches.add(possibleMatch);
}
}
return conceptSource;
if (match == null && !fuzzyMatches.isEmpty()) {
if (fuzzyMatches.size() > 1) {
String msg = "There are " + fuzzyMatches.size() + " possible matching sources for " + name;
throw new IllegalStateException(msg);
}
match = fuzzyMatches.get(0);
}
if (match != null) {
conceptSources.put(name, match);
}
return match;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,11 @@ public static Boolean getAllowDecimal(ConceptNumeric numeric) {
}
}
}

public static String normalizeConceptSourceName(String name) {
return name.toUpperCase()
.replace(" ", "")
.replace("-", "")
.replace("_", "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.openconceptlab;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.openmrs.ConceptSource;
import org.openmrs.api.ConceptService;

import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

public class CacheServiceTest extends MockTest {

@Mock
ConceptService conceptService;

static final ConceptSource ICD_10 = conceptSource("ICD-10");
static final ConceptSource SNOMED_DASH_CT = conceptSource("SNOMED-CT");
static final ConceptSource SNOMED_SPACE_CT = conceptSource("Snomed CT");

public List<ConceptSource> getTestConceptSources() {
List<ConceptSource> l = new ArrayList<>();
l.add(ICD_10);
l.add(SNOMED_DASH_CT);
l.add(SNOMED_SPACE_CT);
return l;
}

public static ConceptSource conceptSource(String name) {
ConceptSource cs = new ConceptSource();
cs.setName(name);
return cs;
}

@Before
public void setupMocks() {
when(conceptService.getAllConceptSources(true)).thenReturn(getTestConceptSources());
}

@Test
public void cacheServiceShouldReturnConceptSourcesWithFuzzyMatching() {
CacheService cacheService = new CacheService(conceptService, null);
assertThat(conceptService.getAllConceptSources(true).size(), is(3));
assertThat(cacheService.getConceptSourceByName("ICD 10"), is(ICD_10));
assertThat(cacheService.getConceptSourceByName("ICD_10"), is(ICD_10));
assertThat(cacheService.getConceptSourceByName("icd 10"), is(ICD_10));
}

@Test
public void cacheServiceShouldReturnConceptSourcesWithExactCaseInsensitiveMatching() {
CacheService cacheService = new CacheService(conceptService, null);
assertThat(conceptService.getAllConceptSources(true).size(), is(3));
assertThat(cacheService.getConceptSourceByName("ICD-10"), is(ICD_10));
assertThat(cacheService.getConceptSourceByName("SNOMED-CT"), is(SNOMED_DASH_CT));
assertThat(cacheService.getConceptSourceByName("Snomed CT"), is(SNOMED_SPACE_CT));
assertThat(cacheService.getConceptSourceByName("icd-10"), is(ICD_10));
assertThat(cacheService.getConceptSourceByName("snomed-CT"), is(SNOMED_DASH_CT));
assertThat(cacheService.getConceptSourceByName("SNOMED CT"), is(SNOMED_SPACE_CT));
}

@Test
public void cacheServiceShouldThrowAnExceptionIfNoExactConceptSourcesAndMultipleFuzzyMatchesAreFound() {
CacheService cacheService = new CacheService(conceptService, null);
Exception actualException = null;
try {
cacheService.getConceptSourceByName("snomedct");
}
catch (Exception e) {
actualException = e;
}
assertThat(actualException, notNullValue());
}
}
11 changes: 11 additions & 0 deletions api/src/test/java/org/openmrs/module/openconceptlab/UtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.openmrs.module.openconceptlab.Utils.normalizeConceptSourceName;
import static org.openmrs.module.openconceptlab.Utils.version5Uuid;

import org.junit.Test;
Expand All @@ -15,4 +17,13 @@ public void version5Uuid_shouldGenerateExpectedUuid() {
assertThat(version5Uuid("Write Code, Save Lives").toString(), equalTo("330fd6a6-43ad-5a84-b406-6006c0869809"));
assertThat(version5Uuid("Medical Record System").toString(), equalTo("be709f07-95e0-5856-8408-684f82d6d894"));
}

@Test
public void normalizeConceptSourceName_shouldNotConsiderSpacesUnderscoresOrDashes() {
assertThat(normalizeConceptSourceName("ICD-10"), equalTo(normalizeConceptSourceName("ICD 10")));
assertThat(normalizeConceptSourceName("ICD-10"), equalTo(normalizeConceptSourceName("ICD10")));
assertThat(normalizeConceptSourceName("SNOMED CT"), equalTo(normalizeConceptSourceName("SNOMED-CT")));
assertThat(normalizeConceptSourceName("snomed_ct"), equalTo(normalizeConceptSourceName("SNOMED-CT")));
assertThat(normalizeConceptSourceName("KenyaEMR"), not(equalTo(normalizeConceptSourceName("KenyaEMR+"))));
}
}

0 comments on commit 2324aac

Please sign in to comment.