Skip to content

Commit

Permalink
Jd 20240704 fix mdm phonetic matching on humanname exception (#6078)
Browse files Browse the repository at this point in the history
* failing test

* fix and changelog

* edit changelog issue number

* mvn spotless

* address code review comment

---------

Co-authored-by: jdar <[email protected]>
  • Loading branch information
jdar8 and jdar authored Jul 12, 2024
1 parent 40d42f3 commit ec7538c
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
type: fix
issue: 6077
title: "Previously, when a MDM rule tried to perform a phonetic match by HumanName (eg. Patient.name), a
`ClassCastException` was thrown. This has now been fixed."
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,17 @@ public boolean matches(String theLeftString, String theRightString) {

@Override
public boolean matches(IBase theLeftBase, IBase theRightBase, MdmMatcherJson theParams) {
String leftString = StringMatcherUtils.extractString((IPrimitiveType<?>) theLeftBase, theParams.getExact());
String rightString = StringMatcherUtils.extractString((IPrimitiveType<?>) theRightBase, theParams.getExact());
if (theLeftBase instanceof IPrimitiveType && theRightBase instanceof IPrimitiveType) {
String leftString = StringMatcherUtils.extractString((IPrimitiveType<?>) theLeftBase, theParams.getExact());
String rightString =
StringMatcherUtils.extractString((IPrimitiveType<?>) theRightBase, theParams.getExact());

return matches(leftString, rightString);
return matches(leftString, rightString);
}
ourLog.warn(
"Unable to evaluate match between {} and {} because they are not an instance of PrimitiveType.",
theLeftBase.getClass().getSimpleName(),
theRightBase.getClass().getSimpleName());
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,29 @@
import ca.uhn.fhir.mdm.rules.json.MdmFieldMatchJson;
import ca.uhn.fhir.mdm.rules.json.MdmMatcherJson;
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
import ca.uhn.fhir.mdm.rules.matcher.fieldmatchers.PhoneticEncoderMatcher;
import ca.uhn.fhir.mdm.rules.matcher.models.MatchTypeEnum;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import org.hl7.fhir.r4.model.HumanName;
import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

public class ResourceMatcherR4Test extends BaseMdmRulesR4Test {
Expand All @@ -23,6 +37,10 @@ public class ResourceMatcherR4Test extends BaseMdmRulesR4Test {
public static final String PHONE_NUMBER = "123 456789";
private Patient myLeft;
private Patient myRight;
@Mock
private Appender<ILoggingEvent> myAppender;
@Captor
ArgumentCaptor<ILoggingEvent> myLoggingEvent;

@Override
@BeforeEach
Expand Down Expand Up @@ -61,6 +79,41 @@ public void testMetaphoneMatchResult() {
assertMatchResult(MdmMatchResultEnum.MATCH, 7L, 3.0, false, false, result);
}

@Test
public void testMetaphoneOnName() {
Logger logger = (Logger) LoggerFactory.getLogger(PhoneticEncoderMatcher.class);
logger.addAppender(myAppender);

// Given: MDM rules that match by Patient.name using some phonetic algorithm
MdmFieldMatchJson lastNameMatchField = new MdmFieldMatchJson()
.setName(PATIENT_FAMILY)
.setResourceType("Patient")
.setResourcePath("name")
.setMatcher(new MdmMatcherJson().setAlgorithm(MatchTypeEnum.METAPHONE));

MdmRulesJson retval = new MdmRulesJson();
retval.setVersion("test version");
retval.addMatchField(lastNameMatchField);
retval.setMdmTypes(List.of("Patient"));
retval.putMatchResult(PATIENT_FAMILY, MdmMatchResultEnum.MATCH);

// When
MdmResourceMatcherSvc matcherSvc = buildMatcher(retval);
MdmMatchOutcome result = matcherSvc.match(myLeft, myRight);

// Then: expect a logged message notifying that we are unable to phonetically match by HumanName
verify(myAppender, times(1)).doAppend(myLoggingEvent.capture());
ILoggingEvent event = myLoggingEvent.getValue();
assertEquals(Level.WARN, event.getLevel());
assertEquals("Unable to evaluate match between HumanName and HumanName because they are not an instance of PrimitiveType.", event.getFormattedMessage());

logger.detachAppender(myAppender);
verifyNoMoreInteractions(myAppender);
System.clearProperty("unit_test");

assertMatchResult(MdmMatchResultEnum.NO_MATCH, 0L, 0.0, false, false, result);
}

@Test
public void testStringMatchResult() {
MdmResourceMatcherSvc matcherSvc = buildMatcher(buildNamePhoneRules(MatchTypeEnum.STRING));
Expand Down

0 comments on commit ec7538c

Please sign in to comment.