Navigation Menu

Skip to content

Commit

Permalink
Merge branch 'master' of github.com:jamesagnew/hapi-fhir
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesagnew committed Jun 19, 2017
2 parents e6cb973 + 10fd88b commit 5789cd2
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 9 deletions.
@@ -0,0 +1,90 @@
package ca.uhn.fhir.rest.client.interceptor;

import static org.apache.commons.lang3.StringUtils.isNotBlank;

/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import ca.uhn.fhir.rest.client.IClientInterceptor;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.api.IHttpResponse;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;

/**
* This interceptor adds an arbitrary header to requests made by this client. Both the
* header name and the header value are specified by the calling code.
*/
public class SimpleRequestHeaderInterceptor implements IClientInterceptor {

private String myHeaderName;
private String myHeaderValue;

/**
* Constructor
*/
public SimpleRequestHeaderInterceptor() {
this(null, null);
}

/**
* Constructor
*/
public SimpleRequestHeaderInterceptor(String theHeaderName, String theHeaderValue) {
super();
myHeaderName = theHeaderName;
myHeaderValue = theHeaderValue;
}

public String getHeaderName() {
return myHeaderName;
}

public String getHeaderValue() {
return myHeaderValue;
}

@Override
public void interceptRequest(IHttpRequest theRequest) {
if (isNotBlank(getHeaderName())) {
theRequest.addHeader(getHeaderName(), getHeaderValue());
}
}

@Override
public void interceptResponse(IHttpResponse theResponse) throws IOException {
// nothing
}

public void setHeaderName(String theHeaderName) {
myHeaderName = theHeaderName;
}

public void setHeaderValue(String theHeaderValue) {
myHeaderValue = theHeaderValue;
}

}
Expand Up @@ -39,6 +39,7 @@
import java.util.Set;

import javax.persistence.TypedQuery;
import javax.servlet.http.HttpServletRequest;

import org.apache.http.NameValuePair;
import org.hl7.fhir.dstu3.model.Bundle;
Expand Down Expand Up @@ -79,6 +80,7 @@
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.PreferReturnEnum;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
Expand Down Expand Up @@ -282,7 +284,7 @@ private Bundle transaction(ServletRequestDetails theRequestDetails, Bundle theRe
super.clearRequestAsProcessingSubRequest(theRequestDetails);
}
}

@SuppressWarnings("unchecked")
private Bundle doTransaction(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName) {
BundleType transactionType = theRequest.getTypeElement().getValue();
Expand Down Expand Up @@ -408,7 +410,7 @@ private Bundle doTransaction(ServletRequestDetails theRequestDetails, Bundle the
String matchUrl = nextReqEntry.getRequest().getIfNoneExist();
outcome = resourceDao.create(res, matchUrl, false, theRequestDetails);
if (nextResourceId != null) {
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
}
entriesToProcess.put(nextRespEntry, outcome.getEntity());
if (outcome.getCreated() == false) {
Expand Down Expand Up @@ -445,12 +447,12 @@ private Bundle doTransaction(ServletRequestDetails theRequestDetails, Bundle the
if (allDeleted.isEmpty()) {
status = Constants.STATUS_HTTP_204_NO_CONTENT;
}

nextRespEntry.getResponse().setOutcome((Resource) deleteOutcome.getOperationOutcome());
}

nextRespEntry.getResponse().setStatus(toStatusString(status));

break;
}
case PUT: {
Expand All @@ -474,7 +476,7 @@ private Bundle doTransaction(ServletRequestDetails theRequestDetails, Bundle the
}
}

handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res, theRequestDetails);
entriesToProcess.put(nextRespEntry, outcome.getEntity());
break;
}
Expand Down Expand Up @@ -646,10 +648,8 @@ private Bundle doTransaction(ServletRequestDetails theRequestDetails, Bundle the
return response;
}



private static void handleTransactionCreateOrUpdateOutcome(Map<IdType, IdType> idSubstitutions, Map<IdType, DaoMethodOutcome> idToPersistedOutcome, IdType nextResourceId, DaoMethodOutcome outcome,
BundleEntryComponent newEntry, String theResourceType, IBaseResource theRes) {
BundleEntryComponent newEntry, String theResourceType, IBaseResource theRes, ServletRequestDetails theRequestDetails) {
IdType newId = (IdType) outcome.getId().toUnqualifiedVersionless();
IdType resourceId = isPlaceholder(nextResourceId) ? nextResourceId : nextResourceId.toUnqualifiedVersionless();
if (newId.equals(resourceId) == false) {
Expand All @@ -668,6 +668,19 @@ private static void handleTransactionCreateOrUpdateOutcome(Map<IdType, IdType> i
newEntry.getResponse().setStatus(toStatusString(Constants.STATUS_HTTP_200_OK));
}
newEntry.getResponse().setLastModified(((Resource) theRes).getMeta().getLastUpdated());

if (theRequestDetails != null) {
if (outcome.getResource() != null) {
String prefer = theRequestDetails.getHeader(Constants.HEADER_PREFER);
PreferReturnEnum preferReturn = RestfulServerUtils.parsePreferHeader(prefer);
if (preferReturn != null) {
if (preferReturn == PreferReturnEnum.REPRESENTATION) {
newEntry.setResource((Resource) outcome.getResource());
}
}
}
}

}

private static boolean isPlaceholder(IdType theId) {
Expand Down
Expand Up @@ -1181,6 +1181,23 @@ public void testSearchLastUpdatedParam() throws InterruptedException {
assertThat(patients, (hasItems(id1a, id1b)));
assertThat(patients, not(hasItems(id2)));
}


{
SearchParameterMap params = new SearchParameterMap();
params.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, beforeR2)));
List<IIdType> patients = toUnqualifiedVersionlessIds(myPatientDao.search(params));
assertThat(patients, not(hasItems(id1a, id1b)));
assertThat(patients, (hasItems(id2)));
}
{
SearchParameterMap params = new SearchParameterMap();
params.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.LESSTHAN_OR_EQUALS, beforeR2)));
List<IIdType> patients = toUnqualifiedVersionlessIds(myPatientDao.search(params));
assertThat(patients, (hasItems(id1a, id1b)));
assertThat(patients, not(hasItems(id2)));
}

}

@SuppressWarnings("deprecation")
Expand Down
Expand Up @@ -1369,6 +1369,53 @@ public void testEverythingPatientOperation() throws Exception {
ourLog.info(ids.toString());
}

@Test
public void testSearchByLastUpdated() throws Exception {
String methodName = "testSearchByLastUpdated";

Patient p = new Patient();
p.addName().setFamily(methodName+"1");
IIdType pid1 = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();

Thread.sleep(10);
long time1 = System.currentTimeMillis();
Thread.sleep(10);

Patient p2 = new Patient();
p2.addName().setFamily(methodName+"2");
IIdType pid2 = ourClient.create().resource(p2).execute().getId().toUnqualifiedVersionless();

HttpGet get = new HttpGet(ourServerBase + "/Patient?_lastUpdated=lt" + new InstantType(new Date(time1)).getValueAsString());
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output);
List<IIdType> ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(pid1));
} finally {
response.close();
}

get = new HttpGet(ourServerBase + "/Patient?_lastUpdated=gt" + new InstantType(new Date(time1)).getValueAsString());
response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output);
List<IIdType> ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(pid2));
} finally {
response.close();
}

}


@Test
public void testEverythingPatientType() throws Exception {
String methodName = "testEverythingPatientType";
Expand Down
Expand Up @@ -60,6 +60,7 @@
import ca.uhn.fhir.jpa.rp.dstu3.PatientResourceProvider;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
Expand All @@ -80,6 +81,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderDstu3Test.class);
private static Server ourServer;
private static String ourServerBase;
private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor;

@Test
public void testTransactionWithInlineConditionalUrl() throws Exception {
Expand Down Expand Up @@ -237,10 +239,17 @@ public void beforeStartServer() throws Exception {
myRestServer.setDefaultResponseEncoding(EncodingEnum.XML);
}

@Before
public void before() {
mySimpleHeaderInterceptor = new SimpleRequestHeaderInterceptor();
ourClient.registerInterceptor(mySimpleHeaderInterceptor);
}

@SuppressWarnings("deprecation")
@After
public void after() {
myRestServer.setUseBrowserFriendlyContentTypes(true);
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
}

@SuppressWarnings("deprecation")
Expand Down Expand Up @@ -632,6 +641,44 @@ public void testTransactionCount() throws Exception {
assertEquals(0, respSub.getEntry().size());
}

@Test
public void testTransactionCreateWithPreferHeader() throws Exception {

Patient p = new Patient();
p.setActive(true);

Bundle req;
Bundle resp;

// No prefer header
req = new Bundle();
req.setType(BundleType.TRANSACTION);
req.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient");
resp = ourClient.transaction().withBundle(req).execute();
assertEquals(null, resp.getEntry().get(0).getResource());
assertEquals("201 Created", resp.getEntry().get(0).getResponse().getStatus());

// Prefer return=minimal
mySimpleHeaderInterceptor.setHeaderName(Constants.HEADER_PREFER);
mySimpleHeaderInterceptor.setHeaderValue(Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_MINIMAL);
req = new Bundle();
req.setType(BundleType.TRANSACTION);
req.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient");
resp = ourClient.transaction().withBundle(req).execute();
assertEquals(null, resp.getEntry().get(0).getResource());
assertEquals("201 Created", resp.getEntry().get(0).getResponse().getStatus());

// Prefer return=representation
mySimpleHeaderInterceptor.setHeaderName(Constants.HEADER_PREFER);
mySimpleHeaderInterceptor.setHeaderValue(Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_REPRESENTATION);
req = new Bundle();
req.setType(BundleType.TRANSACTION);
req.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient");
resp = ourClient.transaction().withBundle(req).execute();
assertEquals(Patient.class, resp.getEntry().get(0).getResource().getClass());
assertEquals("201 Created", resp.getEntry().get(0).getResponse().getStatus());
}

@AfterClass
public static void afterClassClearContext() throws Exception {
ourServer.stop();
Expand Down
Expand Up @@ -27,6 +27,7 @@
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
Expand Down Expand Up @@ -60,6 +61,7 @@
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.PreferReturnEnum;
import ca.uhn.fhir.rest.client.SearchClientDstu3Test.ILocationClient;
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
import ca.uhn.fhir.rest.client.interceptor.CookieInterceptor;
Expand Down Expand Up @@ -177,6 +179,8 @@ public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
OperationOutcome oo = (OperationOutcome) outcome.getOperationOutcome();
assertThat(oo.getText().getDivAsString(), containsString("OK!"));
}



@Test
public void testPatchJsonByIdType() throws Exception {
Expand Down Expand Up @@ -1191,6 +1195,36 @@ public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable
// assertEquals("FAM", resp.getNameFirstRep().getFamilyAsSingleString());
}

@Test
public void testSearchWithNullParameters() throws Exception {
final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});

IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;

DateTimeDt now = DateTimeDt.withCurrentTime();
String dateString = now.getValueAsString().substring(0, 10);

client.search()
.forResource("Patient")
.where(Patient.NAME.matches().value((String)null))
.returnBundle(Bundle.class)
.execute();
assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString());
idx++;
}

@Test
public void testSearchByDate() throws Exception {
final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
Expand Down

0 comments on commit 5789cd2

Please sign in to comment.