Merge pull request #5978
* Fix authorization handling for Bundle resources in the output. When t… * Merge remote-tracking branch 'origin/master' into mm-20240529-test-se… * Add test case for the described scenario * Merge remote-tracking branch 'origin/master' * Add Bundle search test with custom search parameters. * Update test to simpler one to illustrate the problem * SearchParameter for Bundle document referencing resource through comp… * Merge remote-tracking branch 'origin/master' into mm-20240605-search-… * Merge another test into the new class * Remove unused json file. Small formatting fix in a test. * Add more use cases and adjust an existing one
This commit is contained in:
parent
5302a7da52
commit
00a6591586
|
@ -776,7 +776,7 @@ public class BundleUtil {
|
|||
continue;
|
||||
}
|
||||
if (isPlaceholderReference) {
|
||||
if (theUrl.equals(next.getUrl())
|
||||
if (theUrl.equals(next.getFullUrl())
|
||||
|| theUrl.equals(nextResource.getIdElement().getValue())) {
|
||||
return nextResource;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 5988
|
||||
title: "Previously, when creating a custom SearchParameter for a document Bundle that references an entry resource
|
||||
through the composition (e.g. Bundle.entry[0].resource.as(Composition).subject.resolve().as(Patient).identifier),
|
||||
the search using that parameter would not return the matching document Bundle resources, despite the fullUrl of the entry matching the composite reference.
|
||||
This problem does not exist if the reference match can be done against the entry id.
|
||||
However an id is not required so the match should be done against the fullUrl.
|
||||
This issue has been fixed."
|
|
@ -655,15 +655,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
|
||||
public List<String> createResourceLinkPaths(
|
||||
String theResourceName, String theParamName, List<String> theParamQualifiers) {
|
||||
int linkIndex = theParamName.indexOf('.');
|
||||
if (linkIndex == -1) {
|
||||
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
|
||||
if (param == null) {
|
||||
// This can happen during recursion, if not all the possible target types of one link in the chain
|
||||
// support the next link
|
||||
return new ArrayList<>();
|
||||
}
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
|
||||
if (param != null) {
|
||||
List<String> path = param.getPathsSplit();
|
||||
|
||||
/*
|
||||
|
@ -681,40 +674,48 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
}
|
||||
|
||||
return path;
|
||||
} else {
|
||||
}
|
||||
|
||||
boolean containsChain = theParamName.contains(".");
|
||||
if (containsChain) {
|
||||
int linkIndex = theParamName.indexOf('.');
|
||||
String paramNameHead = theParamName.substring(0, linkIndex);
|
||||
String paramNameTail = theParamName.substring(linkIndex + 1);
|
||||
String qualifier = theParamQualifiers.get(0);
|
||||
String qualifier = !theParamQualifiers.isEmpty() ? theParamQualifiers.get(0) : null;
|
||||
List<String> nextQualifiersList = !theParamQualifiers.isEmpty()
|
||||
? theParamQualifiers.subList(1, theParamQualifiers.size())
|
||||
: List.of();
|
||||
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramNameHead);
|
||||
if (param == null) {
|
||||
// This can happen during recursion, if not all the possible target types of one link in the chain
|
||||
// support the next link
|
||||
return new ArrayList<>();
|
||||
param = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramNameHead);
|
||||
if (param != null) {
|
||||
Set<String> tailPaths = param.getTargets().stream()
|
||||
.filter(t -> isBlank(qualifier) || qualifier.equals(t))
|
||||
.map(t -> createResourceLinkPaths(t, paramNameTail, nextQualifiersList))
|
||||
.flatMap(Collection::stream)
|
||||
.map(t -> t.substring(t.indexOf('.') + 1))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
List<String> path = param.getPathsSplit();
|
||||
|
||||
/*
|
||||
* SearchParameters can declare paths on multiple resource
|
||||
* types. Here we only want the ones that actually apply.
|
||||
* Then append all the tail paths to each of the applicable head paths
|
||||
*/
|
||||
return path.stream()
|
||||
.map(String::trim)
|
||||
.filter(t -> t.startsWith(theResourceName + "."))
|
||||
.map(head -> tailPaths.stream()
|
||||
.map(tail -> head + "." + tail)
|
||||
.collect(Collectors.toSet()))
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
Set<String> tailPaths = param.getTargets().stream()
|
||||
.filter(t -> isBlank(qualifier) || qualifier.equals(t))
|
||||
.map(t -> createResourceLinkPaths(
|
||||
t, paramNameTail, theParamQualifiers.subList(1, theParamQualifiers.size())))
|
||||
.flatMap(Collection::stream)
|
||||
.map(t -> t.substring(t.indexOf('.') + 1))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
List<String> path = param.getPathsSplit();
|
||||
|
||||
/*
|
||||
* SearchParameters can declare paths on multiple resource
|
||||
* types. Here we only want the ones that actually apply.
|
||||
* Then append all the tail paths to each of the applicable head paths
|
||||
*/
|
||||
return path.stream()
|
||||
.map(String::trim)
|
||||
.filter(t -> t.startsWith(theResourceName + "."))
|
||||
.map(head ->
|
||||
tailPaths.stream().map(tail -> head + "." + tail).collect(Collectors.toSet()))
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// This can happen during recursion, if not all the possible target types of one link in the chain
|
||||
// support the next link
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private IQueryParameterType mapReferenceChainToRawParamType(
|
||||
|
|
|
@ -3,9 +3,6 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.jpa.util.SqlQuery;
|
||||
import ca.uhn.fhir.parser.StrictErrorHandler;
|
||||
|
@ -13,12 +10,9 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.AuditEvent;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.Composition;
|
||||
import org.hl7.fhir.r4.model.Device;
|
||||
import org.hl7.fhir.r4.model.Encounter;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Location;
|
||||
import org.hl7.fhir.r4.model.MessageHeader;
|
||||
|
@ -27,32 +21,22 @@ import org.hl7.fhir.r4.model.Organization;
|
|||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Quantity;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.hl7.fhir.r4.model.SearchParameter;
|
||||
import org.hl7.fhir.r4.model.StringType;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.countMatches;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
public class ChainingR4SearchTest extends BaseJpaR4Test {
|
||||
|
||||
@Autowired
|
||||
MatchUrlService myMatchUrlService;
|
||||
|
||||
@AfterEach
|
||||
public void after() throws Exception {
|
||||
|
||||
|
@ -359,7 +343,6 @@ public class ChainingR4SearchTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testShouldNotResolveATwoLinkChainWithAContainedResourceWhenContainedResourceIndexingIsTurnedOff() {
|
||||
// setup
|
||||
IIdType oid1;
|
||||
|
||||
{
|
||||
Patient p = new Patient();
|
||||
|
@ -843,8 +826,6 @@ public class ChainingR4SearchTest extends BaseJpaR4Test {
|
|||
// setup
|
||||
myStorageSettings.setIndexOnContainedResources(true);
|
||||
|
||||
IIdType oid1;
|
||||
|
||||
{
|
||||
Organization org = new Organization();
|
||||
org.setId("org");
|
||||
|
@ -1575,79 +1556,6 @@ public class ChainingR4SearchTest extends BaseJpaR4Test {
|
|||
countUnionStatementsInGeneratedQuery("/Observation?subject:Location.name=Smith", 1);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
// search url expected count
|
||||
"/Bundle?composition.patient.identifier=system|value-1&composition.patient.birthdate=1980-01-01, 1, correct identifier correct birthdate",
|
||||
"/Bundle?composition.patient.birthdate=1980-01-01&composition.patient.identifier=system|value-1, 1, correct birthdate correct identifier",
|
||||
"/Bundle?composition.patient.identifier=system|value-1&composition.patient.birthdate=2000-01-01, 0, correct identifier incorrect birthdate",
|
||||
"/Bundle?composition.patient.birthdate=2000-01-01&composition.patient.identifier=system|value-1, 0, incorrect birthdate correct identifier",
|
||||
"/Bundle?composition.patient.identifier=system|value-2&composition.patient.birthdate=1980-01-01, 0, incorrect identifier correct birthdate",
|
||||
"/Bundle?composition.patient.birthdate=1980-01-01&composition.patient.identifier=system|value-2, 0, correct birthdate incorrect identifier",
|
||||
"/Bundle?composition.patient.identifier=system|value-2&composition.patient.birthdate=2000-01-01, 0, incorrect identifier incorrect birthdate",
|
||||
"/Bundle?composition.patient.birthdate=2000-01-01&composition.patient.identifier=system|value-2, 0, incorrect birthdate incorrect identifier",
|
||||
// try sort by composition sp
|
||||
"/Bundle?composition.patient.identifier=system|value-1&_sort=composition.patient.birthdate, 1, correct identifier sort by birthdate",
|
||||
|
||||
})
|
||||
public void testMultipleChainedBundleCompositionSearchParameters(String theSearchUrl, int theExpectedCount, String theMessage) {
|
||||
createSearchParameter("bundle-composition-patient-birthdate",
|
||||
"composition.patient.birthdate",
|
||||
"Bundle",
|
||||
"Bundle.entry.resource.ofType(Patient).birthDate",
|
||||
Enumerations.SearchParamType.DATE
|
||||
);
|
||||
|
||||
createSearchParameter("bundle-composition-patient-identifier",
|
||||
"composition.patient.identifier",
|
||||
"Bundle",
|
||||
"Bundle.entry.resource.ofType(Patient).identifier",
|
||||
Enumerations.SearchParamType.TOKEN
|
||||
);
|
||||
|
||||
createDocumentBundleWithPatientDetails("1980-01-01", "system", "value-1");
|
||||
|
||||
List<String> ids = myTestDaoSearch.searchForIds(theSearchUrl);
|
||||
assertThat(ids).as(theMessage).hasSize(theExpectedCount);
|
||||
}
|
||||
|
||||
private void createSearchParameter(String theId, String theCode, String theBase, String theExpression, Enumerations.SearchParamType theType) {
|
||||
SearchParameter searchParameter = new SearchParameter();
|
||||
searchParameter.setId(theId);
|
||||
searchParameter.setCode(theCode);
|
||||
searchParameter.setName(theCode);
|
||||
searchParameter.setUrl("http://example.org/SearchParameter/" + theId);
|
||||
searchParameter.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
searchParameter.addBase(theBase);
|
||||
searchParameter.setType(theType);
|
||||
searchParameter.setExpression(theExpression);
|
||||
searchParameter = (SearchParameter) mySearchParameterDao.update(searchParameter, mySrd).getResource();
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
assertNotNull(mySearchParamRegistry.getActiveSearchParam(theBase, searchParameter.getName()));
|
||||
}
|
||||
|
||||
private void createDocumentBundleWithPatientDetails(String theBirthDate, String theIdentifierSystem, String theIdentifierValue) {
|
||||
Patient patient = new Patient();
|
||||
patient.setBirthDate(Date.valueOf(theBirthDate));
|
||||
patient.addIdentifier().setSystem(theIdentifierSystem).setValue(theIdentifierValue);
|
||||
patient = (Patient) myPatientDao.create(patient, mySrd).getResource();
|
||||
assertSearchReturns(myPatientDao, SearchParameterMap.newSynchronous(), 1);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.DOCUMENT);
|
||||
Composition composition = new Composition();
|
||||
composition.setType(new CodeableConcept().addCoding(new Coding().setCode("code").setSystem("http://example.org")));
|
||||
bundle.addEntry().setResource(composition);
|
||||
composition.getSubject().setReference(patient.getIdElement().getValue());
|
||||
bundle.addEntry().setResource(patient);
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
assertSearchReturns(myBundleDao, SearchParameterMap.newSynchronous(), 1);
|
||||
}
|
||||
|
||||
private void assertSearchReturns(IFhirResourceDao<?> theDao, SearchParameterMap theSearchParams, int theExpectedCount){
|
||||
assertEquals(theExpectedCount, theDao.search(theSearchParams, mySrd).size());
|
||||
}
|
||||
|
||||
private void countUnionStatementsInGeneratedQuery(String theUrl, int theExpectedNumberOfUnions) {
|
||||
myCaptureQueriesListener.clear();
|
||||
myTestDaoSearch.searchForIds(theUrl);
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.jpa.test.config.TestHSearchAddInConfig;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Composition;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.hl7.fhir.r4.model.SearchParameter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {TestHSearchAddInConfig.NoFT.class})
|
||||
public class FhirResourceDaoR4SearchBundleNoFTTest extends BaseJpaR4Test {
|
||||
@Test
|
||||
public void searchDocumentBundle_withLocalReferenceUsingId_returnsCorrectly() {
|
||||
createBundleSearchParameter("Bundle-composition-patient-identifier",
|
||||
Enumerations.SearchParamType.TOKEN,
|
||||
"composition.patient.identifier",
|
||||
"Bundle.entry[0].resource.as(Composition).subject.resolve().as(Patient).identifier");
|
||||
|
||||
String patientId = "Patient/ABC";
|
||||
String identifierSystem = "http://foo";
|
||||
String identifierValue = "bar";
|
||||
|
||||
String patientUrl = "http://example.com/fhir/" + patientId;
|
||||
|
||||
Composition composition = new Composition();
|
||||
composition.setSubject(new Reference(patientUrl));
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId(patientId);
|
||||
patient.addIdentifier().setSystem(identifierSystem).setValue(identifierValue);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.DOCUMENT);
|
||||
bundle.addEntry().setResource(composition);
|
||||
bundle.addEntry().setResource(patient);
|
||||
|
||||
DaoMethodOutcome createOutcome = myBundleDao.create(bundle, mySrd);
|
||||
assertTrue(createOutcome.getCreated());
|
||||
IIdType bundleId = createOutcome.getId();
|
||||
|
||||
verifySearchCompositionPatientReturnsBundle(identifierSystem, identifierValue, bundleId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchDocumentBundle_withPlaceholderReferenceUsingFullUrl_returnsCorrectly() {
|
||||
createBundleSearchParameter("Bundle-composition-patient-identifier",
|
||||
Enumerations.SearchParamType.TOKEN,
|
||||
"composition.patient.identifier",
|
||||
"Bundle.entry[0].resource.as(Composition).subject.resolve().as(Patient).identifier");
|
||||
|
||||
String patientUrl = "urn:uuid:" + UUID.randomUUID();
|
||||
String identifierSystem = "http://foo";
|
||||
String identifierValue = "bar";
|
||||
|
||||
Composition composition = new Composition();
|
||||
composition.setSubject(new Reference(patientUrl));
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem(identifierSystem).setValue(identifierValue);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.DOCUMENT);
|
||||
bundle.addEntry().setResource(composition);
|
||||
bundle.addEntry().setFullUrl(patientUrl).setResource(patient);
|
||||
|
||||
DaoMethodOutcome createOutcome = myBundleDao.create(bundle, mySrd);
|
||||
assertTrue(createOutcome.getCreated());
|
||||
IIdType bundleId = createOutcome.getId();
|
||||
|
||||
verifySearchCompositionPatientReturnsBundle(identifierSystem, identifierValue, bundleId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchDocumentBundle_withPlaceholderReferenceUsingId_returnsCorrectly() {
|
||||
createBundleSearchParameter("Bundle-composition-patient-identifier",
|
||||
Enumerations.SearchParamType.TOKEN,
|
||||
"composition.patient.identifier",
|
||||
"Bundle.entry[0].resource.as(Composition).subject.resolve().as(Patient).identifier");
|
||||
|
||||
String patientId = "urn:uuid:" + UUID.randomUUID();
|
||||
String identifierSystem = "http://foo";
|
||||
String identifierValue = "bar";
|
||||
|
||||
Composition composition = new Composition();
|
||||
composition.setSubject(new Reference(patientId));
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId(patientId);
|
||||
patient.addIdentifier().setSystem(identifierSystem).setValue(identifierValue);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.DOCUMENT);
|
||||
bundle.addEntry().setResource(composition);
|
||||
bundle.addEntry().setResource(patient);
|
||||
|
||||
DaoMethodOutcome createOutcome = myBundleDao.create(bundle, mySrd);
|
||||
assertTrue(createOutcome.getCreated());
|
||||
IIdType bundleId = createOutcome.getId();
|
||||
|
||||
verifySearchCompositionPatientReturnsBundle(identifierSystem, identifierValue, bundleId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchDocumentBundle_withExternalReference_returnsCorrectly() {
|
||||
String searchParamCode = "composition.subject";
|
||||
createBundleSearchParameter("Bundle-composition-subject",
|
||||
Enumerations.SearchParamType.REFERENCE,
|
||||
searchParamCode,
|
||||
"Bundle.entry[0].resource.as(Composition).subject");
|
||||
|
||||
String patientId = "Patient/ABC";
|
||||
String identifierSystem = "http://foo";
|
||||
String identifierValue = "bar";
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId(patientId);
|
||||
patient.addIdentifier().setSystem(identifierSystem).setValue(identifierValue);
|
||||
DaoMethodOutcome createPatientOutcome = myPatientDao.update(patient, mySrd);
|
||||
assertTrue(createPatientOutcome.getCreated());
|
||||
|
||||
Composition composition = new Composition();
|
||||
composition.getSubject().setReference(createPatientOutcome.getId().toUnqualifiedVersionless().getValue());
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.DOCUMENT);
|
||||
bundle.addEntry().setResource(composition);
|
||||
|
||||
DaoMethodOutcome createBundleOutcome = myBundleDao.create(bundle, mySrd);
|
||||
assertTrue(createBundleOutcome.getCreated());
|
||||
IIdType bundleId = createBundleOutcome.getId();
|
||||
|
||||
verifySearchReturnsBundle(SearchParameterMap.newSynchronous(searchParamCode, new ReferenceParam(patientId)), bundleId);
|
||||
}
|
||||
|
||||
private void verifySearchCompositionPatientReturnsBundle(String theIdentifierSystem, String theIdentifierValue, IIdType theBundleId) {
|
||||
final String systemAndValue = theIdentifierSystem + "|" + theIdentifierValue;
|
||||
verifySearchReturnsBundle(SearchParameterMap.newSynchronous("composition.patient.identifier", new TokenParam(theIdentifierValue)), theBundleId);
|
||||
verifySearchReturnsBundle(SearchParameterMap.newSynchronous("composition.patient.identifier", new TokenParam(theIdentifierSystem, theIdentifierValue)), theBundleId);
|
||||
verifySearchReturnsBundle(SearchParameterMap.newSynchronous("composition", new ReferenceParam("patient.identifier", theIdentifierValue)), theBundleId);
|
||||
verifySearchReturnsBundle(SearchParameterMap.newSynchronous("composition", new ReferenceParam("patient.identifier", systemAndValue)), theBundleId);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"/Bundle?composition.patient.identifier=system|value-1&composition.patient.birthdate=1980-01-01, true, correct identifier correct birthdate",
|
||||
"/Bundle?composition.patient.birthdate=1980-01-01&composition.patient.identifier=system|value-1, true, correct birthdate correct identifier",
|
||||
"/Bundle?composition.patient.identifier=system|value-1&composition.patient.birthdate=2000-01-01, false, correct identifier incorrect birthdate",
|
||||
"/Bundle?composition.patient.birthdate=2000-01-01&composition.patient.identifier=system|value-1, false, incorrect birthdate correct identifier",
|
||||
"/Bundle?composition.patient.identifier=system|value-2&composition.patient.birthdate=1980-01-01, false, incorrect identifier correct birthdate",
|
||||
"/Bundle?composition.patient.birthdate=1980-01-01&composition.patient.identifier=system|value-2, false, correct birthdate incorrect identifier",
|
||||
"/Bundle?composition.patient.identifier=system|value-2&composition.patient.birthdate=2000-01-01, false, incorrect identifier incorrect birthdate",
|
||||
"/Bundle?composition.patient.birthdate=2000-01-01&composition.patient.identifier=system|value-2, false, incorrect birthdate incorrect identifier",
|
||||
// try sort by composition sp
|
||||
"/Bundle?composition.patient.identifier=system|value-1&_sort=composition.patient.birthdate, true, correct identifier sort by birthdate",
|
||||
|
||||
})
|
||||
public void searchDocumentBundle_withExternalReferenceAndEntryCopy_returnsCorrectly(String theSearchUrl, boolean theShouldMatch, String theMessage) {
|
||||
createBundleSearchParameter("bundle-composition-patient-birthdate",
|
||||
Enumerations.SearchParamType.DATE,
|
||||
"composition.patient.birthdate",
|
||||
"Bundle.entry.resource.ofType(Patient).birthDate"
|
||||
);
|
||||
|
||||
createBundleSearchParameter("bundle-composition-patient-identifier",
|
||||
Enumerations.SearchParamType.TOKEN,
|
||||
"composition.patient.identifier",
|
||||
"Bundle.entry.resource.ofType(Patient).identifier"
|
||||
);
|
||||
|
||||
String identifierSystem = "system";
|
||||
String identifierValue = "value-1";
|
||||
String birthDateString = "1980-01-01";
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setBirthDate(Date.valueOf(birthDateString));
|
||||
patient.addIdentifier().setSystem(identifierSystem).setValue(identifierValue);
|
||||
|
||||
DaoMethodOutcome createPatientOutcome = myPatientDao.create(patient, mySrd);
|
||||
assertTrue(createPatientOutcome.getCreated());
|
||||
|
||||
Composition composition = new Composition();
|
||||
composition.setSubject(new Reference(createPatientOutcome.getId().getValue()));
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.DOCUMENT);
|
||||
bundle.addEntry().setResource(composition);
|
||||
bundle.addEntry().setResource(patient);
|
||||
|
||||
DaoMethodOutcome createBundleOutcome = myBundleDao.create(bundle, mySrd);
|
||||
assertTrue(createBundleOutcome.getCreated());
|
||||
IIdType bundleId = createBundleOutcome.getId();
|
||||
|
||||
List<String> ids = myTestDaoSearch.searchForIds(theSearchUrl);
|
||||
if (theShouldMatch) {
|
||||
assertThat(ids).as(theMessage).containsExactlyInAnyOrder(bundleId.getIdPart());
|
||||
} else {
|
||||
assertThat(ids).as(theMessage).hasSize(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void createBundleSearchParameter(String id, Enumerations.SearchParamType theType, String theCode, String theExpression) {
|
||||
SearchParameter sp = new SearchParameter()
|
||||
.setCode(theCode)
|
||||
.addBase("Bundle")
|
||||
.setType(theType)
|
||||
.setExpression(theExpression)
|
||||
.setXpathUsage(SearchParameter.XPathUsageType.NORMAL)
|
||||
.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setId("SearchParameter/" + id);
|
||||
sp.setUrl("http://example.com/fhir/" + sp.getId());
|
||||
ourLog.info("SP: {}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(sp));
|
||||
IBaseResource resource = mySearchParameterDao.update(sp, mySrd).getResource();
|
||||
assertNotNull(resource);
|
||||
}
|
||||
|
||||
private void verifySearchReturnsBundle(SearchParameterMap theSearchParameterMap, IIdType theBundleId) {
|
||||
IBundleProvider searchOutcome = myBundleDao.search(theSearchParameterMap, mySrd);
|
||||
assertEquals(1, searchOutcome.size());
|
||||
assertEquals(theBundleId, searchOutcome.getAllResources().get(0).getIdElement());
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import ca.uhn.fhir.batch2.jobs.reindex.ReindexAppCtx;
|
||||
import ca.uhn.fhir.batch2.model.JobInstance;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
|
@ -27,7 +26,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.ClasspathUtil;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Appointment;
|
||||
import org.hl7.fhir.r4.model.Appointment.AppointmentStatus;
|
||||
|
@ -36,13 +34,11 @@ import org.hl7.fhir.r4.model.ChargeItem;
|
|||
import org.hl7.fhir.r4.model.CodeType;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.Composition;
|
||||
import org.hl7.fhir.r4.model.Condition;
|
||||
import org.hl7.fhir.r4.model.DateTimeType;
|
||||
import org.hl7.fhir.r4.model.DateType;
|
||||
import org.hl7.fhir.r4.model.DecimalType;
|
||||
import org.hl7.fhir.r4.model.DiagnosticReport;
|
||||
import org.hl7.fhir.r4.model.Encounter;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
|
||||
import org.hl7.fhir.r4.model.Extension;
|
||||
|
@ -74,9 +70,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static org.apache.commons.lang3.StringUtils.countMatches;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
@ -304,48 +299,6 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
|
|||
mySearchParamRegistry.forceRefresh();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBundleComposition() {
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.setCode("foo");
|
||||
fooSp.addBase("Bundle");
|
||||
fooSp.setType(Enumerations.SearchParamType.REFERENCE);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setExpression("Bundle.entry[0].resource.as(Composition).encounter");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.r4.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
|
||||
ourLog.debug(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(fooSp));
|
||||
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
Encounter enc = new Encounter();
|
||||
enc.setStatus(Encounter.EncounterStatus.ARRIVED);
|
||||
String encId = myEncounterDao.create(enc).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Composition composition = new Composition();
|
||||
composition.getEncounter().setReference(encId);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.DOCUMENT);
|
||||
bundle.addEntry().setResource(composition);
|
||||
|
||||
ourLog.debug(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
|
||||
String bundleId = myBundleDao.create(bundle).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
SearchParameterMap map;
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.setLoadSynchronous(true);
|
||||
map.add("foo", new ReferenceParam(encId));
|
||||
IBundleProvider results = myBundleDao.search(map);
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).contains(bundleId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateInvalidUnquotedExtensionUrl() {
|
||||
String invalidExpression = "Patient.extension.where(url=http://foo).value";
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
|
@ -89,7 +85,6 @@ import org.hl7.fhir.r4.model.CodeableConcept;
|
|||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.Communication;
|
||||
import org.hl7.fhir.r4.model.CommunicationRequest;
|
||||
import org.hl7.fhir.r4.model.Composition;
|
||||
import org.hl7.fhir.r4.model.Condition;
|
||||
import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem;
|
||||
import org.hl7.fhir.r4.model.DateTimeType;
|
||||
|
@ -144,8 +139,6 @@ import org.junit.jupiter.api.DisplayName;
|
|||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -184,12 +177,13 @@ import static ca.uhn.fhir.util.DateUtils.convertDateToIso8601String;
|
|||
import static org.apache.commons.lang3.StringUtils.countMatches;
|
||||
import static org.apache.commons.lang3.StringUtils.leftPad;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -5733,95 +5727,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Index for
|
||||
* [base]/Bundle?composition.patient.identifier=foo
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"true , urn:uuid:5c34dc2c-9b5d-4ec1-b30b-3e2d4371508b , urn:uuid:5c34dc2c-9b5d-4ec1-b30b-3e2d4371508b",
|
||||
"false, urn:uuid:5c34dc2c-9b5d-4ec1-b30b-3e2d4371508b , urn:uuid:5c34dc2c-9b5d-4ec1-b30b-3e2d4371508b",
|
||||
"true , Patient/ABC , Patient/ABC ",
|
||||
"false, Patient/ABC , Patient/ABC ",
|
||||
"true , Patient/ABC , http://example.com/fhir/Patient/ABC ",
|
||||
"false, Patient/ABC , http://example.com/fhir/Patient/ABC ",
|
||||
})
|
||||
public void testCreateAndSearchForFullyChainedSearchParameter(boolean theUseFullChainInName, String thePatientId, String theFullUrl) {
|
||||
// Setup 1
|
||||
|
||||
myStorageSettings.setIndexMissingFields(JpaStorageSettings.IndexEnabledEnum.DISABLED);
|
||||
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/Bundle-composition-patient-identifier");
|
||||
sp.setCode("composition.patient.identifier");
|
||||
sp.setName("composition.patient.identifier");
|
||||
sp.setUrl("http://example.org/SearchParameter/Bundle-composition-patient-identifier");
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setExpression("Bundle.entry[0].resource.as(Composition).subject.resolve().as(Patient).identifier");
|
||||
sp.addBase("Bundle");
|
||||
ourLog.info("SP: {}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(sp));
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
// Test 1
|
||||
|
||||
Composition composition = new Composition();
|
||||
composition.setSubject(new Reference(thePatientId));
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId(new IdType(theFullUrl));
|
||||
patient.addIdentifier().setSystem("http://foo").setValue("bar");
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.DOCUMENT);
|
||||
bundle
|
||||
.addEntry()
|
||||
.setResource(composition);
|
||||
bundle
|
||||
.addEntry()
|
||||
.setFullUrl(theFullUrl)
|
||||
.setResource(patient);
|
||||
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
|
||||
Bundle bundle2 = new Bundle();
|
||||
bundle2.setType(Bundle.BundleType.DOCUMENT);
|
||||
myBundleDao.create(bundle2, mySrd);
|
||||
|
||||
// Test
|
||||
|
||||
SearchParameterMap map;
|
||||
if (theUseFullChainInName) {
|
||||
map = SearchParameterMap.newSynchronous("composition.patient.identifier", new TokenParam("http://foo", "bar"));
|
||||
} else {
|
||||
map = SearchParameterMap.newSynchronous("composition", new ReferenceParam("patient.identifier", "http://foo|bar"));
|
||||
}
|
||||
IBundleProvider outcome = myBundleDao.search(map, mySrd);
|
||||
|
||||
// Verify
|
||||
|
||||
List<String> params = extractAllTokenIndexes();
|
||||
assertThat(params).as(params.toString()).containsExactlyInAnyOrder("composition.patient.identifier http://foo|bar");
|
||||
assertEquals(1, outcome.size());
|
||||
}
|
||||
|
||||
private List<String> extractAllTokenIndexes() {
|
||||
List<String> params = runInTransaction(() -> {
|
||||
logAllTokenIndexes();
|
||||
|
||||
return myResourceIndexedSearchParamTokenDao
|
||||
.findAll()
|
||||
.stream()
|
||||
.filter(t -> t.getParamName().contains("."))
|
||||
.map(t -> t.getParamName() + " " + t.getSystem() + "|" + t.getValue())
|
||||
.toList();
|
||||
});
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
public class TagBelowTests {
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.search.builder.predicate;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
||||
|
@ -15,6 +16,8 @@ import com.healthmarketscience.sqlbuilder.InCondition;
|
|||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSchema;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSpec;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
@ -27,11 +30,13 @@ import java.util.Collections;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.anyCollection;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
|
@ -48,7 +53,7 @@ public class ResourceLinkPredicateBuilderTest {
|
|||
private ISearchParamRegistry mySearchParamRegistry;
|
||||
|
||||
@Mock
|
||||
private IIdHelperService myIdHelperService;
|
||||
private IIdHelperService<?> myIdHelperService;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
|
@ -64,14 +69,14 @@ public class ResourceLinkPredicateBuilderTest {
|
|||
@Test
|
||||
public void createEverythingPredicate_withListOfPids_returnsInPredicate() {
|
||||
when(myResourceLinkPredicateBuilder.generatePlaceholders(anyCollection())).thenReturn(List.of(PLACEHOLDER_BASE + "1", PLACEHOLDER_BASE + "2"));
|
||||
Condition condition = myResourceLinkPredicateBuilder.createEverythingPredicate("Patient", new ArrayList<>(), 1l, 2l);
|
||||
Condition condition = myResourceLinkPredicateBuilder.createEverythingPredicate("Patient", new ArrayList<>(), 1L, 2L);
|
||||
assertEquals(InCondition.class, condition.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createEverythingPredicate_withSinglePid_returnsInCondition() {
|
||||
when(myResourceLinkPredicateBuilder.generatePlaceholders(anyCollection())).thenReturn(List.of(PLACEHOLDER_BASE + "1"));
|
||||
Condition condition = myResourceLinkPredicateBuilder.createEverythingPredicate("Patient", new ArrayList<>(), 1l);
|
||||
Condition condition = myResourceLinkPredicateBuilder.createEverythingPredicate("Patient", new ArrayList<>(), 1L);
|
||||
assertEquals(BinaryCondition.class, condition.getClass());
|
||||
}
|
||||
|
||||
|
@ -100,4 +105,79 @@ public class ResourceLinkPredicateBuilderTest {
|
|||
.hasMessage("HAPI-2498: Unsupported search modifier(s): \"[:identifier, :x, :y]\" for resource type \"Observation\". Valid search modifiers are: [:contains, :exact, :in, :iterate, :missing, :not-in, :of-type, :recurse, :text]");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createResourceLinkPaths_withoutChainAndSearchParameterFoundNoQualifiers_returnsFilteredPaths() {
|
||||
String paramName = "param.name";
|
||||
String resourceType = "Bundle";
|
||||
RuntimeSearchParam mockSearchParam = mock(RuntimeSearchParam.class);
|
||||
when(mockSearchParam.getPathsSplit()).thenReturn(List.of("Patient.given", "Bundle.composition.subject", "Bundle.type"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam(resourceType, paramName)).thenReturn(mockSearchParam);
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of());
|
||||
MatcherAssert.assertThat(result, Matchers.containsInAnyOrder("Bundle.composition.subject", "Bundle.type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createResourceLinkPaths_withoutChainAndSearchParameterNotFoundNoQualifiers_returnsEmpty() {
|
||||
String paramName = "param.name";
|
||||
String resourceType = "Bundle";
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of());
|
||||
MatcherAssert.assertThat(result, Matchers.empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createResourceLinkPaths_withChainAndSearchParameterFoundNoQualifiers_returnsPath() {
|
||||
String paramName = "subject.identifier";
|
||||
String resourceType = "Observation";
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject.identifier")).thenReturn(null);
|
||||
RuntimeSearchParam observationSubjectSP = mock(RuntimeSearchParam.class);
|
||||
when(observationSubjectSP.getPathsSplit()).thenReturn(List.of("Observation.subject"));
|
||||
when(observationSubjectSP.getTargets()).thenReturn(Set.of("Patient"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject")).thenReturn(observationSubjectSP);
|
||||
RuntimeSearchParam patientIdentifierSP = mock(RuntimeSearchParam.class);
|
||||
when(patientIdentifierSP.getPathsSplit()).thenReturn(List.of("Patient.identifier"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Patient", "identifier")).thenReturn(patientIdentifierSP);
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of());
|
||||
MatcherAssert.assertThat(result, Matchers.containsInAnyOrder("Observation.subject.identifier"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createResourceLinkPaths_withChainAndSearchParameterFoundWithQualifiers_returnsPath() {
|
||||
String paramName = "subject.managingOrganization.identifier";
|
||||
String resourceType = "Observation";
|
||||
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject.managingOrganization.identifier")).thenReturn(null);
|
||||
|
||||
RuntimeSearchParam observationSubjectSP = mock(RuntimeSearchParam.class);
|
||||
when(observationSubjectSP.getPathsSplit()).thenReturn(List.of("Observation.subject"));
|
||||
when(observationSubjectSP.getTargets()).thenReturn(Set.of("Patient"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject")).thenReturn(observationSubjectSP);
|
||||
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Patient", "managingOrganization.identifier")).thenReturn(null);
|
||||
|
||||
RuntimeSearchParam organizationSP = mock(RuntimeSearchParam.class);
|
||||
when(organizationSP.getPathsSplit()).thenReturn(List.of("Patient.managingOrganization"));
|
||||
when(organizationSP.getTargets()).thenReturn(Set.of("Organization"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Patient", "managingOrganization")).thenReturn(organizationSP);
|
||||
|
||||
RuntimeSearchParam organizationIdentifierSP = mock(RuntimeSearchParam.class);
|
||||
when(organizationIdentifierSP.getPathsSplit()).thenReturn(List.of("Organization.identifier"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Organization", "identifier")).thenReturn(organizationIdentifierSP);
|
||||
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of("Patient", "Organization"));
|
||||
MatcherAssert.assertThat(result, Matchers.containsInAnyOrder("Observation.subject.managingOrganization.identifier"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createResourceLinkPaths_withChainAndSearchParameterFoundWithNonMatchingQualifier_returnsEmpty() {
|
||||
String paramName = "subject.identifier";
|
||||
String resourceType = "Observation";
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject.identifier")).thenReturn(null);
|
||||
RuntimeSearchParam observationSubjectSP = mock(RuntimeSearchParam.class);
|
||||
when(observationSubjectSP.getPathsSplit()).thenReturn(List.of("Observation.subject"));
|
||||
when(observationSubjectSP.getTargets()).thenReturn(Set.of("Patient"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject")).thenReturn(observationSubjectSP);
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of("Group"));
|
||||
MatcherAssert.assertThat(result, Matchers.empty());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue