Avoid NPE in concept mapping (#2637)

This commit is contained in:
James Agnew 2021-05-06 05:25:38 -04:00 committed by GitHub
parent a4856bba17
commit 1424d48912
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 170 additions and 55 deletions

View File

@ -202,69 +202,68 @@ public class TermConceptMappingSvcImpl implements ITermConceptMappingSvc {
termConceptMap = myConceptMapDao.save(termConceptMap);
int codesSaved = 0;
if (theConceptMap.hasGroup()) {
TermConceptMapGroup termConceptMapGroup;
for (ConceptMap.ConceptMapGroupComponent group : theConceptMap.getGroup()) {
TermConceptMapGroup termConceptMapGroup;
for (ConceptMap.ConceptMapGroupComponent group : theConceptMap.getGroup()) {
String groupSource = group.getSource();
if (isBlank(groupSource)) {
groupSource = source;
}
if (isBlank(groupSource)) {
throw new UnprocessableEntityException("ConceptMap[url='" + theConceptMap.getUrl() + "'] contains at least one group without a value in ConceptMap.group.source");
}
String groupSource = group.getSource();
if (isBlank(groupSource)) {
groupSource = source;
}
if (isBlank(groupSource)) {
throw new UnprocessableEntityException("ConceptMap[url='" + theConceptMap.getUrl() + "'] contains at least one group without a value in ConceptMap.group.source");
}
String groupTarget = group.getTarget();
if (isBlank(groupTarget)) {
groupTarget = target;
}
if (isBlank(groupTarget)) {
throw new UnprocessableEntityException("ConceptMap[url='" + theConceptMap.getUrl() + "'] contains at least one group without a value in ConceptMap.group.target");
}
String groupTarget = group.getTarget();
if (isBlank(groupTarget)) {
groupTarget = target;
}
if (isBlank(groupTarget)) {
throw new UnprocessableEntityException("ConceptMap[url='" + theConceptMap.getUrl() + "'] contains at least one group without a value in ConceptMap.group.target");
}
termConceptMapGroup = new TermConceptMapGroup();
termConceptMapGroup.setConceptMap(termConceptMap);
termConceptMapGroup.setSource(groupSource);
termConceptMapGroup.setSourceVersion(group.getSourceVersion());
termConceptMapGroup.setTarget(groupTarget);
termConceptMapGroup.setTargetVersion(group.getTargetVersion());
myConceptMapGroupDao.save(termConceptMapGroup);
termConceptMapGroup = new TermConceptMapGroup();
termConceptMapGroup.setConceptMap(termConceptMap);
termConceptMapGroup.setSource(groupSource);
termConceptMapGroup.setSourceVersion(group.getSourceVersion());
termConceptMapGroup.setTarget(groupTarget);
termConceptMapGroup.setTargetVersion(group.getTargetVersion());
termConceptMapGroup = myConceptMapGroupDao.save(termConceptMapGroup);
if (group.hasElement()) {
TermConceptMapGroupElement termConceptMapGroupElement;
for (ConceptMap.SourceElementComponent element : group.getElement()) {
if (isBlank(element.getCode())) {
continue;
}
termConceptMapGroupElement = new TermConceptMapGroupElement();
termConceptMapGroupElement.setConceptMapGroup(termConceptMapGroup);
termConceptMapGroupElement.setCode(element.getCode());
termConceptMapGroupElement.setDisplay(element.getDisplay());
myConceptMapGroupElementDao.save(termConceptMapGroupElement);
if (group.hasElement()) {
TermConceptMapGroupElement termConceptMapGroupElement;
for (ConceptMap.SourceElementComponent element : group.getElement()) {
if (isBlank(element.getCode())) {
continue;
}
termConceptMapGroupElement = new TermConceptMapGroupElement();
termConceptMapGroupElement.setConceptMapGroup(termConceptMapGroup);
termConceptMapGroupElement.setCode(element.getCode());
termConceptMapGroupElement.setDisplay(element.getDisplay());
termConceptMapGroupElement = myConceptMapGroupElementDao.save(termConceptMapGroupElement);
if (element.hasTarget()) {
TermConceptMapGroupElementTarget termConceptMapGroupElementTarget;
for (ConceptMap.TargetElementComponent elementTarget : element.getTarget()) {
if (isBlank(elementTarget.getCode())) {
continue;
}
termConceptMapGroupElementTarget = new TermConceptMapGroupElementTarget();
termConceptMapGroupElementTarget.setConceptMapGroupElement(termConceptMapGroupElement);
termConceptMapGroupElementTarget.setCode(elementTarget.getCode());
termConceptMapGroupElementTarget.setDisplay(elementTarget.getDisplay());
termConceptMapGroupElementTarget.setEquivalence(elementTarget.getEquivalence());
myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget);
if (element.hasTarget()) {
TermConceptMapGroupElementTarget termConceptMapGroupElementTarget;
for (ConceptMap.TargetElementComponent elementTarget : element.getTarget()) {
if (isBlank(elementTarget.getCode())) {
continue;
}
termConceptMapGroupElementTarget = new TermConceptMapGroupElementTarget();
termConceptMapGroupElementTarget.setConceptMapGroupElement(termConceptMapGroupElement);
termConceptMapGroupElementTarget.setCode(elementTarget.getCode());
termConceptMapGroupElementTarget.setDisplay(elementTarget.getDisplay());
termConceptMapGroupElementTarget.setEquivalence(elementTarget.getEquivalence());
myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget);
if (++codesSaved % 250 == 0) {
ourLog.info("Have saved {} codes in ConceptMap", codesSaved);
myConceptMapGroupElementTargetDao.flush();
}
if (++codesSaved % 250 == 0) {
ourLog.info("Have saved {} codes in ConceptMap", codesSaved);
myConceptMapGroupElementTargetDao.flush();
}
}
}
}
}
}
} else {
TermConceptMap existingTermConceptMap = optionalExistingTermConceptMapByUrl.get();
@ -558,9 +557,9 @@ public class TermConceptMappingSvcImpl implements ITermConceptMappingSvc {
private boolean alreadyContainsMapping(List<TranslateConceptResult> elements, TranslateConceptResult translationMatch) {
for (TranslateConceptResult nextExistingElement : elements) {
if (nextExistingElement.getSystem().equals(translationMatch.getSystem())) {
if (nextExistingElement.getSystemVersion().equals(translationMatch.getSystemVersion())) {
if (nextExistingElement.getCode().equals(translationMatch.getCode())) {
if (StringUtils.equals(nextExistingElement.getSystem(), translationMatch.getSystem())) {
if (StringUtils.equals(nextExistingElement.getSystemVersion(), translationMatch.getSystemVersion())) {
if (StringUtils.equals(nextExistingElement.getCode(), translationMatch.getCode())) {
return true;
}
}

View File

@ -4,6 +4,9 @@ import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.TranslateConceptResult;
import ca.uhn.fhir.context.support.TranslateConceptResults;
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
import ca.uhn.fhir.jpa.dao.data.ITermConceptMapGroupDao;
import ca.uhn.fhir.jpa.dao.data.ITermConceptMapGroupElementDao;
import ca.uhn.fhir.jpa.dao.data.ITermConceptMapGroupElementTargetDao;
import ca.uhn.fhir.jpa.entity.TermConceptMap;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.CanonicalType;
@ -16,6 +19,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.TransactionStatus;
@ -38,7 +42,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class FhirResourceDaoR4ConceptMapTest extends BaseJpaR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4ConceptMapTest.class);
@Autowired
protected ITermConceptMapGroupDao myConceptMapGroupDao;
@Autowired
protected ITermConceptMapGroupElementDao myConceptMapGroupElementDao;
@Autowired
protected ITermConceptMapGroupElementTargetDao myConceptMapGroupElementTargetDao;
private IIdType myConceptMapId;
@BeforeEach
@ -597,6 +606,113 @@ public class FhirResourceDaoR4ConceptMapTest extends BaseJpaR4Test {
});
}
/**
* Make sure we can handle mapping where the system has no explicit version
* specified in the ConceptMap
*/
@Test
public void testTranslateWithReverse_NonVersionedSystem() {
ConceptMap conceptMap1 = new ConceptMap();
conceptMap1.setUrl(CM_URL);
conceptMap1.setSource(new UriType(VS_URL));
conceptMap1.setTarget(new UriType(VS_URL_2));
ConceptMap.ConceptMapGroupComponent group = conceptMap1.addGroup();
group.setSource(CS_URL);
group.setTarget(CS_URL_2);
ConceptMap.SourceElementComponent element = group.addElement();
element.setCode("12345");
element.setDisplay("Source Code 12345");
ConceptMap.TargetElementComponent target = element.addTarget();
target.setCode("34567");
target.setDisplay("Target Code 34567");
target.setEquivalence(ConceptMapEquivalence.EQUAL);
element = group.addElement();
element.setCode("23456");
element.setDisplay("Source Code 23456");
target = element.addTarget();
target.setCode("45678");
target.setDisplay("Target Code 45678");
target.setEquivalence(ConceptMapEquivalence.WIDER);
group = conceptMap1.addGroup();
group.setSource(CS_URL);
group.setTarget(CS_URL_3);
element = group.addElement();
element.setCode("12345");
element.setDisplay("Source Code 12345");
target = element.addTarget();
target.setCode("56789");
target.setDisplay("Target Code 56789");
target.setEquivalence(ConceptMapEquivalence.EQUAL);
target = element.addTarget();
target.setCode("67890");
target.setDisplay("Target Code 67890");
target.setEquivalence(ConceptMapEquivalence.WIDER);
group = conceptMap1.addGroup();
group.setSource(CS_URL_4);
group.setTarget(CS_URL_2);
element = group.addElement();
element.setCode("12345");
element.setDisplay("Source Code 12345");
target = element.addTarget();
target.setCode("34567");
target.setDisplay("Target Code 34567");
target.setEquivalence(ConceptMapEquivalence.NARROWER);
conceptMap1.setId(myConceptMapId);
myConceptMapDao.update(conceptMap1, mySrd).getId().toUnqualifiedVersionless();
runInTransaction(() -> {
/*
* Provided:
* source code
* reverse = true
*/
TranslationRequest translationRequest = new TranslationRequest();
translationRequest.getCodeableConcept().addCoding()
.setCode("34567");
translationRequest.setReverse(true);
TranslateConceptResults translationResult = myConceptMapDao.translate(translationRequest, null);
assertTrue(translationResult.getResult());
assertEquals("Matches found", translationResult.getMessage());
assertEquals(2, translationResult.getResults().size());
TranslateConceptResult translationMatch = translationResult.getResults().get(0);
assertEquals(ConceptMapEquivalence.EQUAL.toCode(), translationMatch.getEquivalence());
assertEquals("12345", translationMatch.getCode());
assertEquals("Source Code 12345", translationMatch.getDisplay());
assertEquals(CS_URL, translationMatch.getSystem());
assertEquals(null, translationMatch.getSystemVersion());
assertEquals(CM_URL, translationMatch.getConceptMapUrl());
translationMatch = translationResult.getResults().get(1);
assertEquals(ConceptMapEquivalence.NARROWER.toCode(), translationMatch.getEquivalence());
assertEquals("12345", translationMatch.getCode());
assertEquals("Source Code 12345", translationMatch.getDisplay());
assertEquals(CS_URL_4, translationMatch.getSystem());
assertEquals(null, translationMatch.getSystemVersion());
assertEquals(CM_URL, translationMatch.getConceptMapUrl());
});
}
@Test
public void testTranslateWithReverseHavingEquivalence() {
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);