improve nickname matcher (#3628)
* improve nickname matcher * change log * review feedback and fix test
This commit is contained in:
parent
1c70e97087
commit
df76b0f8f1
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 3628
|
||||
title: "Nickname matching only matched formal names to a nickname. This has been broadened to match nicknames to other
|
||||
nicknames for the same formal name."
|
|
@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -70,7 +71,7 @@ public class NicknameInterceptor {
|
|||
toRemove.add(stringParam);
|
||||
//First, attempt to expand as a formal name
|
||||
String name = stringParam.getValue().toLowerCase(Locale.ROOT);
|
||||
List<String> expansions = myNicknameSvc.getEquivalentNames(name);
|
||||
Collection<String> expansions = myNicknameSvc.getEquivalentNames(name);
|
||||
if (expansions == null) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.searchparam.nickname;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -57,11 +58,15 @@ class NicknameMap {
|
|||
return myFormalToNick.size();
|
||||
}
|
||||
|
||||
List<String> getNicknamesFromFormalNameOrNull(String theName) {
|
||||
return myFormalToNick.get(theName);
|
||||
@Nonnull
|
||||
List<String> getNicknamesFromFormalName(String theName) {
|
||||
List<String> result = myFormalToNick.get(theName);
|
||||
return result == null ? new ArrayList<>() : result;
|
||||
}
|
||||
|
||||
List<String> getFormalNamesFromNicknameOrNull(String theNickname) {
|
||||
return myNicknameToFormal.get(theNickname);
|
||||
@Nonnull
|
||||
List<String> getFormalNamesFromNickname(String theNickname) {
|
||||
List<String> result = myNicknameToFormal.get(theNickname);
|
||||
return result == null ? new ArrayList<>() : result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,15 @@ package ca.uhn.fhir.jpa.searchparam.nickname;
|
|||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class NicknameSvc {
|
||||
private final NicknameMap myNicknameMap = new NicknameMap();
|
||||
|
@ -46,28 +49,27 @@ public class NicknameSvc {
|
|||
return myNicknameMap.size();
|
||||
}
|
||||
|
||||
public List<String> getEquivalentNames(String theName) {
|
||||
List<String> retval = new ArrayList<>();
|
||||
retval.add(theName);
|
||||
public Collection<String> getEquivalentNames(String theName) {
|
||||
Set<String> retval = new HashSet<>(getNicknamesFromFormalName(theName));
|
||||
|
||||
List<String> expansions;
|
||||
expansions = getNicknamesFromFormalNameOrNull(theName);
|
||||
if (expansions != null) {
|
||||
retval.addAll(expansions);
|
||||
} else {
|
||||
expansions = getFormalNamesFromNicknameOrNull(theName);
|
||||
if (expansions != null) {
|
||||
retval.addAll(expansions);
|
||||
if (retval.isEmpty()) {
|
||||
List<String> formalNames = getFormalNamesFromNickname(theName);
|
||||
retval.addAll(formalNames);
|
||||
for (String formalName : formalNames) {
|
||||
retval.addAll(getNicknamesFromFormalName(formalName));
|
||||
}
|
||||
}
|
||||
retval.add(theName);
|
||||
return retval;
|
||||
}
|
||||
|
||||
List<String> getNicknamesFromFormalNameOrNull(String theName) {
|
||||
return myNicknameMap.getNicknamesFromFormalNameOrNull(theName);
|
||||
@Nonnull
|
||||
List<String> getNicknamesFromFormalName(String theName) {
|
||||
return myNicknameMap.getNicknamesFromFormalName(theName);
|
||||
}
|
||||
|
||||
List<String> getFormalNamesFromNicknameOrNull(String theNickname) {
|
||||
return myNicknameMap.getFormalNamesFromNicknameOrNull(theNickname);
|
||||
@Nonnull
|
||||
List<String> getFormalNamesFromNickname(String theNickname) {
|
||||
return myNicknameMap.getFormalNamesFromNickname(theNickname);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ class NicknameInterceptorTest {
|
|||
|
||||
// verify
|
||||
String newSearch = sp.toNormalizedQueryString(null);
|
||||
assertEquals("?name=ken,kendall,kendrick,kendrik,kenneth,kenny,kent,mckenna", newSearch);
|
||||
assertEquals("?name=ken,kendall,kendrick,kendrik,kenna,kenneth,kenny,kent,mckenna,meaka", newSearch);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -24,7 +24,7 @@ kent,ken,kenny,kendrick
|
|||
NicknameMap map = new NicknameMap();
|
||||
map.load(new StringReader(testData));
|
||||
assertEquals(7, map.size());
|
||||
assertThat(map.getNicknamesFromFormalNameOrNull("kenneth"), containsInAnyOrder("ken", "kenny", "kendrick"));
|
||||
assertThat(map.getFormalNamesFromNicknameOrNull("ken"), containsInAnyOrder("kendall", "kendrick", "kendrik", "kenneth", "kenny", "kent"));
|
||||
assertThat(map.getNicknamesFromFormalName("kenneth"), containsInAnyOrder("ken", "kenny", "kendrick"));
|
||||
assertThat(map.getFormalNamesFromNickname("ken"), containsInAnyOrder("kendall", "kendrick", "kendrik", "kenneth", "kenny", "kent"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.i18n.Msg;
|
|||
import ca.uhn.fhir.jpa.searchparam.nickname.NicknameSvc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -44,7 +45,12 @@ public class NicknameMatcher implements IMdmStringMatcher {
|
|||
String leftString = theLeftString.toLowerCase(Locale.ROOT);
|
||||
String rightString = theRightString.toLowerCase(Locale.ROOT);
|
||||
|
||||
List<String> leftNames = myNicknameSvc.getEquivalentNames(leftString);
|
||||
return leftNames.contains(rightString);
|
||||
Collection<String> leftNames = myNicknameSvc.getEquivalentNames(leftString);
|
||||
if (leftNames.contains(rightString)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Collection<String> rightNames = myNicknameSvc.getEquivalentNames(rightString);
|
||||
return rightNames.contains(leftString);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,12 @@ class NicknameMatcherTest {
|
|||
assertTrue(matcher.matches("Kenneth", "Kenny"));
|
||||
assertTrue(matcher.matches("Ken", "Kenneth"));
|
||||
assertTrue(matcher.matches("Kenny", "Kenneth"));
|
||||
assertTrue(matcher.matches("Jim", "Jimmy"));
|
||||
assertTrue(matcher.matches("Jimmy", "Jim"));
|
||||
assertTrue(matcher.matches("Jim", "James"));
|
||||
assertTrue(matcher.matches("Jimmy", "James"));
|
||||
assertTrue(matcher.matches("James", "Jimmy"));
|
||||
assertTrue(matcher.matches("James", "Jim"));
|
||||
|
||||
assertFalse(matcher.matches("Ken", "Bob"));
|
||||
// These aren't nickname matches. If you want matches like these use a phonetic matcher
|
||||
|
|
Loading…
Reference in New Issue