Fix #822 - Respect chained method params in a transaction search

This commit is contained in:
James Agnew 2018-01-30 16:20:25 -06:00
parent c5165e860b
commit 1c5a07b5a0
14 changed files with 261 additions and 178 deletions

View File

@ -69,14 +69,12 @@ public class TokenOrListParam extends BaseOrListParam<TokenOrListParam, TokenPar
/**
* Add a new token to this list
*
* @param theSystem
* @param theSystem
* The system to use for the one token to pre-populate in this list
* @param theValue
* The value to use for the one token to pre-populate in this list
*/
public void add(String theSystem, String theValue) {
public TokenOrListParam add(String theSystem, String theValue) {
add(new TokenParam(theSystem, theValue));
return this;
}
public List<BaseCodingDt> getListAsCodings() {

View File

@ -114,7 +114,7 @@ public class JaxRsResponseDstu3Test {
boolean allowPrefer = true;
String resourceName = "Patient";
MethodOutcome methodOutcome = new MethodOutcome(theId);
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
response.getRequestDetails().addParameter(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
boolean addContentLocationHeader = true;
boolean respondGzip = true;
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request);
@ -126,7 +126,7 @@ public class JaxRsResponseDstu3Test {
@Test
public void testNoOutcomeXml() throws IOException {
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
response.getRequestDetails().addParameter(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
boolean addContentLocationHeader = true;
boolean respondGzip = true;
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), null, theSummaryMode, 204, addContentLocationHeader, respondGzip, this.request);

View File

@ -88,7 +88,7 @@ public class JaxRsResponseTest {
@Test
public void testReturnResponseAsXml() throws IOException {
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML });
response.getRequestDetails().addParameter(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML });
boolean addContentLocationHeader = true;
boolean respondGzip = true;
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request);
@ -100,7 +100,7 @@ public class JaxRsResponseTest {
@Test
public void testNoOutcomeXml() throws IOException {
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML });
response.getRequestDetails().addParameter(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML });
boolean addContentLocationHeader = true;
boolean respondGzip = true;
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request);

View File

@ -532,7 +532,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
}
for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]);
requestDetails.getParameters().put(nextParamEntry.getKey(), nextValue);
requestDetails.addParameter(nextParamEntry.getKey(), nextValue);
}
url = url.substring(0, qIndex);
}

View File

@ -260,7 +260,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
}
for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]);
requestDetails.getParameters().put(nextParamEntry.getKey(), nextValue);
requestDetails.addParameter(nextParamEntry.getKey(), nextValue);
}
url = url.substring(0, qIndex);
}

View File

@ -266,7 +266,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
}
for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]);
requestDetails.getParameters().put(nextParamEntry.getKey(), nextValue);
requestDetails.addParameter(nextParamEntry.getKey(), nextValue);
}
url = url.substring(0, qIndex);
}
@ -290,7 +290,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
requestDetails.addHeader(Constants.HEADER_IF_NONE_MATCH, nextReqEntry.getRequest().getIfNoneMatch());
}
Validate.isTrue(method instanceof BaseResourceReturningMethodBinding, "Unable to handle GET {}", url);
Validate.isTrue(method instanceof BaseResourceReturningMethodBinding, "Unable to handle GET {0}", url);
try {
IBaseResource resource = ((BaseResourceReturningMethodBinding) method).doInvokeServer(theRequestDetails.getServer(), requestDetails);
if (paramValues.containsKey(Constants.PARAM_SUMMARY) || paramValues.containsKey(Constants.PARAM_CONTENT)) {

View File

@ -29,13 +29,13 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
public class ServletSubRequestDetails extends ServletRequestDetails {
private Map<String, ArrayList<String>> myHeaders = new HashMap<String, ArrayList<String>>();
private Map<String, ArrayList<String>> myHeaders = new HashMap<>();
public void addHeader(String theName, String theValue) {
String lowerCase = theName.toLowerCase();
ArrayList<String> list = myHeaders.get(lowerCase);
if (list == null) {
list = new ArrayList<String>();
list = new ArrayList<>();
myHeaders.put(lowerCase, list);
}
list.add(theValue);

View File

@ -158,7 +158,7 @@ public abstract class BaseJpaTest {
}
protected List<IIdType> toUnqualifiedVersionlessIds(IBundleProvider theFound) {
List<IIdType> retVal = new ArrayList<IIdType>();
List<IIdType> retVal = new ArrayList<>();
Integer size = theFound.size();
StopWatch sw = new StopWatch();
while (size == null) {
@ -171,6 +171,7 @@ public abstract class BaseJpaTest {
} catch (InterruptedException theE) {
//ignore
}
size = theFound.size();
}
ourLog.info("Found {} results", size);

View File

@ -3,7 +3,6 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
@ -12,11 +11,11 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*;
@ -25,7 +24,6 @@ import org.hl7.fhir.r4.model.Observation.ObservationStatus;
import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
@ -57,46 +55,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
}
/**
* See #811
*/
@Test
public void testUpdatePreviouslyDeletedResourceInBatch() {
AllergyIntolerance ai = new AllergyIntolerance();
ai.setId("AIA1914009");
ai.setClinicalStatus(AllergyIntolerance.AllergyIntoleranceClinicalStatus.ACTIVE);
IIdType id = myAllergyIntoleranceDao.update(ai).getId();
assertEquals("1", id.getVersionIdPart());
id = myAllergyIntoleranceDao.delete(ai.getIdElement().toUnqualifiedVersionless()).getId();
assertEquals("2", id.getVersionIdPart());
try {
myAllergyIntoleranceDao.read(ai.getIdElement().toUnqualifiedVersionless());
fail();
} catch (ResourceGoneException e) {
// good
}
Bundle batch = new Bundle();
batch.setType(BundleType.BATCH);
ai = new AllergyIntolerance();
ai.setId("AIA1914009");
ai.setClinicalStatus(AllergyIntolerance.AllergyIntoleranceClinicalStatus.ACTIVE);
batch
.addEntry()
.setFullUrl("AllergyIntolerance/AIA1914009")
.setResource(ai)
.getRequest()
.setUrl("AllergyIntolerance/AIA1914009")
.setMethod(HTTPVerb.PUT);
mySystemDao.transaction(mySrd, batch);
id = myAllergyIntoleranceDao.read(ai.getIdElement().toUnqualifiedVersionless()).getIdElement();
assertEquals("3", id.getVersionIdPart());
}
@Before
public void beforeDisableResultReuse() {
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
@ -2489,7 +2447,7 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
/*
* Make sure we are able to handle placeholder IDs in match URLs, e.g.
*
*
* "request": {
* "method": "PUT",
* "url": "Observation?subject=urn:uuid:8dba64a8-2aca-48fe-8b4e-8c7bf2ab695a&code=http%3A%2F%2Floinc.org|29463-7&date=2011-09-03T11:13:00-04:00"
@ -2519,7 +2477,7 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
/*
* Make sure we are able to handle placeholder IDs in match URLs, e.g.
*
*
* "request": {
* "method": "PUT",
* "url": "Observation?subject=urn:uuid:8dba64a8-2aca-48fe-8b4e-8c7bf2ab695a&code=http%3A%2F%2Floinc.org|29463-7&date=2011-09-03T11:13:00-04:00"
@ -2583,7 +2541,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString());
}
@Test
public void testTransactionWithReferenceResource() {
Bundle request = new Bundle();
@ -2611,7 +2568,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
assertEquals(1, found.size().intValue());
}
@Test
public void testTransactionWithReferenceToCreateIfNoneExist() {
Bundle bundle = new Bundle();
@ -2635,9 +2591,9 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
IdType medId1 = new IdType(outcome.getEntry().get(0).getResponse().getLocation());
IdType medOrderId1 = new IdType(outcome.getEntry().get(1).getResponse().getLocation());
/*
* Again!
*/
/*
* Again!
*/
bundle = new Bundle();
bundle.setType(BundleType.TRANSACTION);
@ -2665,6 +2621,33 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
assertNotEquals(medOrderId1, medOrderId2);
}
@Test
public void testTransactionWithReferenceUuid() {
Bundle request = new Bundle();
Patient p = new Patient();
p.setActive(true);
p.setId(IdType.newRandomUuid());
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl(p.getId());
Observation o = new Observation();
o.getCode().setText("Some Observation");
o.getSubject().setReference(p.getId());
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST);
Bundle resp = mySystemDao.transaction(mySrd, request);
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
String patientId = new IdType(resp.getEntry().get(0).getResponse().getLocation()).toUnqualifiedVersionless().getValue();
assertThat(patientId, startsWith("Patient/"));
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronous(true);
params.add("subject", new ReferenceParam(patientId));
IBundleProvider found = myObservationDao.search(params);
assertEquals(1, found.size().intValue());
}
//
//
// /**
@ -2767,34 +2750,6 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
//
// }
@Test
public void testTransactionWithReferenceUuid() {
Bundle request = new Bundle();
Patient p = new Patient();
p.setActive(true);
p.setId(IdType.newRandomUuid());
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl(p.getId());
Observation o = new Observation();
o.getCode().setText("Some Observation");
o.getSubject().setReference(p.getId());
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerb.POST);
Bundle resp = mySystemDao.transaction(mySrd, request);
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
String patientId = new IdType(resp.getEntry().get(0).getResponse().getLocation()).toUnqualifiedVersionless().getValue();
assertThat(patientId, startsWith("Patient/"));
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronous(true);
params.add("subject", new ReferenceParam(patientId));
IBundleProvider found = myObservationDao.search(params);
assertEquals(1, found.size().intValue());
}
@Test
public void testTransactionWithRelativeOidIds() throws Exception {
Bundle res = new Bundle();
@ -2959,6 +2914,46 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
}
/**
* See #811
*/
@Test
public void testUpdatePreviouslyDeletedResourceInBatch() {
AllergyIntolerance ai = new AllergyIntolerance();
ai.setId("AIA1914009");
ai.setClinicalStatus(AllergyIntolerance.AllergyIntoleranceClinicalStatus.ACTIVE);
IIdType id = myAllergyIntoleranceDao.update(ai).getId();
assertEquals("1", id.getVersionIdPart());
id = myAllergyIntoleranceDao.delete(ai.getIdElement().toUnqualifiedVersionless()).getId();
assertEquals("2", id.getVersionIdPart());
try {
myAllergyIntoleranceDao.read(ai.getIdElement().toUnqualifiedVersionless());
fail();
} catch (ResourceGoneException e) {
// good
}
Bundle batch = new Bundle();
batch.setType(BundleType.BATCH);
ai = new AllergyIntolerance();
ai.setId("AIA1914009");
ai.setClinicalStatus(AllergyIntolerance.AllergyIntoleranceClinicalStatus.ACTIVE);
batch
.addEntry()
.setFullUrl("AllergyIntolerance/AIA1914009")
.setResource(ai)
.getRequest()
.setUrl("AllergyIntolerance/AIA1914009")
.setMethod(HTTPVerb.PUT);
mySystemDao.transaction(mySrd, batch);
id = myAllergyIntoleranceDao.read(ai.getIdElement().toUnqualifiedVersionless()).getIdElement();
assertEquals("3", id.getVersionIdPart());
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();

View File

@ -1,35 +1,41 @@
package ca.uhn.fhir.jpa.provider.r4;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.rp.r4.*;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.TestUtil;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.*;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.r4.model.Patient;
import org.junit.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.rp.r4.*;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.TestUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
@ -43,7 +49,6 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor;
@SuppressWarnings("deprecation")
@After
public void after() {
@ -57,7 +62,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
mySimpleHeaderInterceptor = new SimpleRequestHeaderInterceptor();
ourClient.registerInterceptor(mySimpleHeaderInterceptor);
}
@Before
public void beforeStartServer() throws Exception {
if (myRestServer == null) {
@ -73,8 +78,14 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
organizationRp.setDao(myOrganizationDao);
MedicationResourceProvider medicationRp = new MedicationResourceProvider();
medicationRp.setDao(myMedicationDao);
MedicationRequestResourceProvider medicationRequestRp = new MedicationRequestResourceProvider();
medicationRequestRp.setDao(myMedicationRequestDao);
RestfulServer restServer = new RestfulServer(ourCtx);
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp);
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp, medicationRequestRp, medicationRp);
restServer.setPlainProviders(mySystemProvider);
@ -106,11 +117,10 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
ourClient.setLogRequestAndResponse(true);
myRestServer = restServer;
}
myRestServer.setDefaultResponseEncoding(EncodingEnum.XML);
myRestServer.setPagingProvider(myPagingProvider);
}
private List<String> create20Patients() {
List<String> ids = new ArrayList<String>();
@ -120,7 +130,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
patient.setId("" + letter);
patient.setGender(AdministrativeGender.MALE);
patient.addIdentifier().setSystem("urn:foo").setValue("A");
patient.addName().setFamily("abcdefghijklmnopqrstuvwxyz".substring(i, i+1));
patient.addName().setFamily("abcdefghijklmnopqrstuvwxyz".substring(i, i + 1));
String id = myPatientDao.update(patient).getId().toUnqualifiedVersionless().getValue();
ids.add(id);
}
@ -130,7 +140,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
@Test
public void testBatchWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleType.BATCH);
input
@ -138,12 +148,12 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100);
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size());
@ -151,11 +161,11 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
}
@Test
public void testBatchWithGetNormalSearch() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleType.BATCH);
input
@ -163,16 +173,16 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&_sort=name");
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size());
List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
String nextPageLink = respBundle.getLink("next").getUrl();
output = ourClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute();
respBundle = output;
@ -188,7 +198,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
public void testBatchWithManyGets() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleType.BATCH);
for (int i = 0; i < 30; i++) {
@ -198,10 +208,10 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&identifier=urn:foo|A,AAAAA" + i);
}
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(30, output.getEntry().size());
for (int i = 0; i < 30; i++) {
Bundle respBundle = (Bundle) output.getEntry().get(i).getResource();
@ -212,10 +222,72 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
}
}
/**
* See #822
*/
@Test
public void testSearchByBatch() {
Patient p = new Patient();
p.setId("P3000254749");
p.setActive(true);
myPatientDao.update(p);
Medication med = new Medication();
med.setId("MED19795");
med.getCode().addCoding().setCode("00093-0058-05").setSystem("http://hl7.org/fhir/sid/ndc");
myMedicationDao.update(med);
med = new Medication();
med.setId("MED20344");
med.getCode().addCoding().setCode("50580-0449-23").setSystem("http://hl7.org/fhir/sid/ndc");
myMedicationDao.update(med);
MedicationRequest medRequest = new MedicationRequest();
medRequest.setId("MR142528");
medRequest.setMedication(new Reference("Medication/MED19795"));
medRequest.setSubject(new Reference("Patient/P3000254749"));
medRequest.setIntent(MedicationRequest.MedicationRequestIntent.ORDER);
myMedicationRequestDao.update(medRequest);
medRequest = new MedicationRequest();
medRequest.setId("MR635079");
medRequest.setMedication(new Reference("Medication/MED20344"));
medRequest.setSubject(new Reference("Patient/P3000254749"));
medRequest.setIntent(MedicationRequest.MedicationRequestIntent.ORDER);
myMedicationRequestDao.update(medRequest);
SearchParameterMap map = new SearchParameterMap();
map.add(MedicationRequest.SP_INTENT, new TokenOrListParam().add(null, "plan").add(null, "order"));
map.add(MedicationRequest.SP_MEDICATION, new ReferenceParam().setChain("code").setValue("50580-0449-23"));
Bundle b = ourClient
.search()
.forResource("MedicationRequest")
.where(MedicationRequest.INTENT.exactly().codes("plan", "order"))
.and(MedicationRequest.MEDICATION.hasChainedProperty(Medication.CODE.exactly().code("50580-0449-23")))
.returnBundle(Bundle.class)
.execute();
assertEquals(1, b.getEntry().size());
assertEquals("MedicationRequest/MR635079", b.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
b = new Bundle();
b.setType(BundleType.BATCH);
b.addEntry()
.setFullUrl(IdType.newRandomUuid().getValueAsString())
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("MedicationRequest?intent=plan,order&medication.code=50580-0449-23&patient=P3000254749");
Bundle resp = ourClient.transaction().withBundle(b).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
b = (Bundle) resp.getEntry().get(0).getResource();
assertEquals(1, b.getEntry().size());
assertEquals("MedicationRequest/MR635079", b.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
}
@Test
public void testTransactionWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleType.TRANSACTION);
input
@ -223,12 +295,12 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100);
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size());
@ -236,11 +308,11 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
}
@Test
public void testTransactionWithGetNormalSearch() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleType.TRANSACTION);
input
@ -248,16 +320,16 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&_sort=name");
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size());
List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
String nextPageLink = respBundle.getLink("next").getUrl();
output = ourClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute();
respBundle = output;
@ -273,7 +345,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
public void testTransactionWithManyGets() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleType.TRANSACTION);
for (int i = 0; i < 30; i++) {
@ -283,10 +355,10 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5&identifier=urn:foo|A,AAAAA" + i);
}
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(30, output.getEntry().size());
for (int i = 0; i < 30; i++) {
Bundle respBundle = (Bundle) output.getEntry().get(i).getResource();

View File

@ -7,6 +7,7 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@ -30,9 +31,9 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -63,6 +64,11 @@ public abstract class RequestDetails {
private Map<String, List<String>> myUnqualifiedToQualifiedNames;
private Map<Object, Object> myUserData;
public void addParameter(String theName, String[] theValues) {
getParameters();
myParameters.put(theName, theValues);
}
protected abstract byte[] getByteStreamRequestContents();
/**
@ -170,37 +176,14 @@ public abstract class RequestDetails {
public Map<String, String[]> getParameters() {
if (myParameters == null) {
return Collections.emptyMap();
myParameters = new HashMap<>();
}
return myParameters;
return Collections.unmodifiableMap(myParameters);
}
public void setParameters(Map<String, String[]> theParams) {
myParameters = theParams;
for (String next : theParams.keySet()) {
for (int i = 0; i < next.length(); i++) {
char nextChar = next.charAt(i);
if (nextChar == ':' || nextChar == '.') {
if (myUnqualifiedToQualifiedNames == null) {
myUnqualifiedToQualifiedNames = new HashMap<>();
}
String unqualified = next.substring(0, i);
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
if (list == null) {
list = new ArrayList<>(4);
myUnqualifiedToQualifiedNames.put(unqualified, list);
}
list.add(next);
break;
}
}
}
if (myUnqualifiedToQualifiedNames == null) {
myUnqualifiedToQualifiedNames = Collections.emptyMap();
}
myUnqualifiedToQualifiedNames = null;
}
/**
@ -296,6 +279,29 @@ public abstract class RequestDetails {
}
public Map<String, List<String>> getUnqualifiedToQualifiedNames() {
for (String next : myParameters.keySet()) {
for (int i = 0; i < next.length(); i++) {
char nextChar = next.charAt(i);
if (nextChar == ':' || nextChar == '.') {
if (myUnqualifiedToQualifiedNames == null) {
myUnqualifiedToQualifiedNames = new HashMap<>();
}
String unqualified = next.substring(0, i);
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
if (list == null) {
list = new ArrayList<>(4);
myUnqualifiedToQualifiedNames.put(unqualified, list);
}
list.add(next);
break;
}
}
}
if (myUnqualifiedToQualifiedNames == null) {
myUnqualifiedToQualifiedNames = Collections.emptyMap();
}
return myUnqualifiedToQualifiedNames;
}
@ -359,6 +365,12 @@ public abstract class RequestDetails {
return myRequestContents;
}
public void removeParameter(String theName) {
Validate.notNull(theName, "theName must not be null");
getParameters();
myParameters.remove(theName);
}
/**
* This method may be used to modify the contents of the incoming
* request by hardcoding a value which will be used instead of the

View File

@ -938,8 +938,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
/*
* If we're handling an exception, no summary mode should be applied
*/
requestDetails.getParameters().remove(Constants.PARAM_SUMMARY);
requestDetails.getParameters().remove(Constants.PARAM_ELEMENTS);
requestDetails.removeParameter(Constants.PARAM_SUMMARY);
requestDetails.removeParameter(Constants.PARAM_ELEMENTS);
/*
* If nobody handles it, default behaviour is to stream back the OperationOutcome to the client.

View File

@ -323,10 +323,10 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
force = true;
} else if (Constants.FORMATS_HTML_XML.equals(formatParam)) {
force = true;
theRequestDetails.getParameters().put(Constants.PARAM_FORMAT, PARAM_FORMAT_VALUE_XML);
theRequestDetails.addParameter(Constants.PARAM_FORMAT, PARAM_FORMAT_VALUE_XML);
} else if (Constants.FORMATS_HTML_JSON.equals(formatParam)) {
force = true;
theRequestDetails.getParameters().put(Constants.PARAM_FORMAT, PARAM_FORMAT_VALUE_JSON);
theRequestDetails.addParameter(Constants.PARAM_FORMAT, PARAM_FORMAT_VALUE_JSON);
} else {
return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse);
}

View File

@ -88,6 +88,11 @@
which automaticaly converts response payloads to a client-specified version
according to transforms built into FHIR.
</action>
<action type="fix" issue="822">
Searches which were embedded in a Bundle as a transaction or batch operation did
not respect any chained method parameters (e.g. MedicationRequest?medication.code=123).
Thanks to @manjusampath for reporting!
</action>
</release>
<release version="3.2.0" date="2018-01-13">
<action type="add">