Don't error out on missing CS (#1570)
* Don't error out on mi9ssing CS * Add tests * Add a bit of test coverage * One more test
This commit is contained in:
parent
9d4df3e470
commit
007cfaf00e
|
@ -1,4 +1,5 @@
|
|||
|
||||
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.expansionRefersToUnknownCs=Unknown CodeSystem URI "{0}" referenced from ValueSet
|
||||
|
||||
# Core Library Messages
|
||||
ca.uhn.fhir.context.FhirContext.unknownResourceName=Unknown resource name "{0}" (this name is not known in FHIR version "{1}")
|
||||
|
|
|
@ -675,7 +675,10 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
|
|||
|
||||
CodeSystem codeSystemFromContext = getCodeSystemFromContext(system);
|
||||
if (codeSystemFromContext == null) {
|
||||
throw new InvalidRequestException("Unknown code system: " + system);
|
||||
String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "expansionRefersToUnknownCs", system);
|
||||
ourLog.warn(msg);
|
||||
theValueSetCodeAccumulator.addMessage(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!theIncludeOrExclude.getConcept().isEmpty()) {
|
||||
|
|
|
@ -27,6 +27,8 @@ import java.util.Collection;
|
|||
|
||||
public interface IValueSetConceptAccumulator {
|
||||
|
||||
void addMessage(String theMessage);
|
||||
|
||||
void includeConcept(String theSystem, String theCode, String theDisplay);
|
||||
|
||||
void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection<TermConceptDesignation> theDesignations);
|
||||
|
|
|
@ -57,6 +57,12 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
myConceptsExcluded = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessage(String theMessage) {
|
||||
// ignore for now
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void includeConcept(String theSystem, String theCode, String theDisplay) {
|
||||
saveConcept(theSystem, theCode, theDisplay);
|
||||
|
@ -82,7 +88,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
if (optionalConcept.isPresent()) {
|
||||
TermValueSetConcept concept = optionalConcept.get();
|
||||
|
||||
ourLog.info("Excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
ourLog.debug("Excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
for (TermValueSetConceptDesignation designation : concept.getDesignations()) {
|
||||
myValueSetConceptDesignationDao.deleteById(designation.getId());
|
||||
myTermValueSet.decrementTotalConceptDesignations();
|
||||
|
@ -90,7 +96,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
myValueSetConceptDao.deleteById(concept.getId());
|
||||
myTermValueSet.decrementTotalConcepts();
|
||||
myValueSetDao.save(myTermValueSet);
|
||||
ourLog.info("Done excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
ourLog.debug("Done excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
|
||||
if (++myConceptsExcluded % 250 == 0) {
|
||||
ourLog.info("Have excluded {} concepts from ValueSet[{}]", myConceptsExcluded, myTermValueSet.getUrl());
|
||||
|
|
|
@ -22,9 +22,11 @@ package ca.uhn.fhir.jpa.term;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
||||
import ca.uhn.fhir.model.api.annotation.Block;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.r4.model.StringType;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -54,6 +56,13 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V
|
|||
return myMaxCapacity - myConceptsCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessage(String theMessage) {
|
||||
addExtension()
|
||||
.setUrl(JpaConstants.EXT_VALUESET_EXPANSION_MESSAGE)
|
||||
.setValue(new StringType(theMessage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void includeConcept(String theSystem, String theCode, String theDisplay) {
|
||||
incrementConceptsCount();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.r5;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.util.TestUtil;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
|
@ -9,11 +11,14 @@ import ca.uhn.fhir.rest.param.HasOrListParam;
|
|||
import ca.uhn.fhir.rest.param.HasParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import org.hl7.fhir.r5.model.Organization;
|
||||
import org.hl7.fhir.r5.model.Patient;
|
||||
import org.hl7.fhir.r5.model.Practitioner;
|
||||
import org.hl7.fhir.r5.model.PractitionerRole;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@SuppressWarnings({"unchecked", "Duplicates"})
|
||||
|
@ -98,6 +103,40 @@ public class FhirResourceDaoR5SearchNoFtTest extends BaseJpaR5Test {
|
|||
assertEquals(1, outcome.getResources(0, 1).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchDoesntFailIfResourcesAreDeleted() {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setValue("1");
|
||||
myPatientDao.create(p);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setValue("2");
|
||||
myPatientDao.create(p);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setValue("3");
|
||||
Long id = myPatientDao.create(p).getId().getIdPartAsLong();
|
||||
|
||||
IBundleProvider outcome = myPatientDao.search(new SearchParameterMap());
|
||||
assertEquals(3, outcome.size().intValue());
|
||||
|
||||
runInTransaction(()->{
|
||||
ResourceTable table = myResourceTableDao.findById(id).orElseThrow(() -> new IllegalArgumentException());
|
||||
table.setDeleted(new Date());
|
||||
myResourceTableDao.save(table);
|
||||
});
|
||||
|
||||
assertEquals(2, outcome.getResources(0, 3).size());
|
||||
|
||||
runInTransaction(()->{
|
||||
myResourceHistoryTableDao.deleteAll();
|
||||
});
|
||||
|
||||
assertEquals(0, outcome.getResources(0, 3).size());
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDesignationDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermValueSetDao;
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ValueSetConceptAccumulatorTest {
|
||||
|
||||
private ValueSetConceptAccumulator myAccumulator;
|
||||
private TermValueSet myValueSet;
|
||||
@Mock
|
||||
private ITermValueSetDao myValueSetDao;
|
||||
@Mock
|
||||
private ITermValueSetConceptDesignationDao myValueSetDesignationDao;
|
||||
@Mock
|
||||
private ITermValueSetConceptDao myValueSetConceptDao;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myValueSet = new TermValueSet();
|
||||
myAccumulator = new ValueSetConceptAccumulator(myValueSet, myValueSetDao, myValueSetConceptDao, myValueSetDesignationDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncludeConcept() {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
myAccumulator.includeConcept("sys", "code", "display");
|
||||
}
|
||||
verify(myValueSetConceptDao, times(1000)).save(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludeBlankConcept() {
|
||||
myAccumulator.excludeConcept("", "");
|
||||
verifyNoInteractions(myValueSetConceptDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddMessage() {
|
||||
myAccumulator.addMessage("foo");
|
||||
verifyNoInteractions(myValueSetConceptDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludeConceptWithDesignations() {
|
||||
for (int i = 0; i <1000; i++) {
|
||||
|
||||
TermValueSetConcept value = new TermValueSetConcept();
|
||||
value.setCode("code");
|
||||
value.getDesignations().add(new TermValueSetConceptDesignation().setValue("foo"));
|
||||
|
||||
when(myValueSetConceptDao.findByTermValueSetIdSystemAndCode(any(), eq("sys"), eq("code"+i))).thenReturn(Optional.of(value));
|
||||
|
||||
myAccumulator.excludeConcept("sys", "code"+i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,11 +2,13 @@ package ca.uhn.fhir.jpa.term;
|
|||
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.Extension;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.hl7.fhir.r4.model.codesystems.HttpVerb;
|
||||
import org.junit.Test;
|
||||
|
@ -688,6 +690,21 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
assertEquals("Systolische bloeddruk minimaal 1 uur", designationComponent.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandValueSetWithUnknownCodeSystem() {
|
||||
ValueSet vs = new ValueSet();
|
||||
ValueSet.ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem("http://unknown-system");
|
||||
ValueSet outcome = myTermSvc.expandValueSetInMemory(vs, null);
|
||||
assertEquals(0, outcome.getExpansion().getContains().size());
|
||||
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome);
|
||||
ourLog.info(encoded);
|
||||
|
||||
Extension extensionByUrl = outcome.getExpansion().getExtensionByUrl(JpaConstants.EXT_VALUESET_EXPANSION_MESSAGE);
|
||||
assertEquals("Unknown CodeSystem URI \"http://unknown-system\" referenced from ValueSet", extensionByUrl.getValueAsPrimitive().getValueAsString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExpandTermValueSetAndChildrenWithOffsetAndCountWithClientAssignedId() throws Exception {
|
||||
myDaoConfig.setPreExpandValueSets(true);
|
||||
|
|
|
@ -24,6 +24,13 @@ import ca.uhn.fhir.rest.api.Constants;
|
|||
|
||||
public class JpaConstants {
|
||||
|
||||
/**
|
||||
* Non-instantiable
|
||||
*/
|
||||
private JpaConstants() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation name for the $apply-codesystem-delta-add operation
|
||||
*/
|
||||
|
@ -243,6 +250,12 @@ public class JpaConstants {
|
|||
*/
|
||||
public static final String EXTENSION_EXT_SYSTEMDEFINED = JpaConstants.class.getName() + "_EXTENSION_EXT_SYSTEMDEFINED";
|
||||
|
||||
/**
|
||||
* Message added to expansion valueset
|
||||
*/
|
||||
public static final String EXT_VALUESET_EXPANSION_MESSAGE = "http://hapifhir.io/fhir/StructureDefinition/valueset-expansion-message";
|
||||
|
||||
|
||||
/**
|
||||
* Parameter for the $export operation
|
||||
*/
|
||||
|
|
|
@ -11,6 +11,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
@ -50,7 +52,17 @@ public class SubscriptionLoaderTest extends BaseBlockingQueueSubscribableChannel
|
|||
@Test
|
||||
public void testMultipleThreadsDontBlock() throws InterruptedException {
|
||||
SubscriptionLoader svc = new SubscriptionLoader();
|
||||
svc.acquireSemaphoreForUnitTest();
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
new Thread(()->{
|
||||
try {
|
||||
svc.acquireSemaphoreForUnitTest();
|
||||
latch.countDown();
|
||||
} catch (InterruptedException theE) {
|
||||
// ignore
|
||||
}
|
||||
}).start();
|
||||
|
||||
latch.await(10, TimeUnit.SECONDS);
|
||||
svc.syncSubscriptions();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue