Fix #831 - Remove useless TagListParam annotation

This commit is contained in:
jamesagnew 2018-01-26 10:03:21 -05:00
parent 6b366a58f7
commit 2e4f80d7a3
9 changed files with 294 additions and 573 deletions

View File

@ -1,42 +0,0 @@
package ca.uhn.fhir.rest.annotation;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2018 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.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import ca.uhn.fhir.model.api.TagList;
/**
* Parameter annotation for the {@link TagList} parameter in a {@link GetTags},
* {@link AddTags}, or {@link DeleteTags} method.
*
* @see GetTags
* @see AddTags
* @see DeleteTags
*/
@Target(value = ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TagListParam {
// nothing
}

View File

@ -1,7 +1,28 @@
package ca.uhn.fhir.rest.param; package ca.uhn.fhir.rest.param;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.binder.QueryParameterAndBinder;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/* /*
* #%L * #%L
* HAPI FHIR - Core Library * HAPI FHIR - Core Library
@ -11,9 +32,9 @@ import java.lang.reflect.Method;
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -21,29 +42,9 @@ import java.lang.reflect.Method;
* limitations under the License. * limitations under the License.
* #L% * #L%
*/ */
import java.util.*;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.TagListParam;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.binder.QueryParameterAndBinder;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.UrlUtil;
public class ParameterUtil { public class ParameterUtil {
private static final String LABEL = "label=\"";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ParameterUtil.class);
private static final String SCHEME = "scheme=\"";
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends IIdType> T convertIdToType(IIdType value, Class<T> theIdParamType) { public static <T extends IIdType> T convertIdToType(IIdType value, Class<T> theIdParamType) {
if (value != null && !theIdParamType.isAssignableFrom(value.getClass())) { if (value != null && !theIdParamType.isAssignableFrom(value.getClass())) {
@ -179,8 +180,7 @@ public class ParameterUtil {
public static Integer findParamAnnotationIndex(Method theMethod, Class<?> toFind) { public static Integer findParamAnnotationIndex(Method theMethod, Class<?> toFind) {
int paramIndex = 0; int paramIndex = 0;
for (Annotation[] annotations : theMethod.getParameterAnnotations()) { for (Annotation[] annotations : theMethod.getParameterAnnotations()) {
for (int annotationIndex = 0; annotationIndex < annotations.length; annotationIndex++) { for (Annotation nextAnnotation : annotations) {
Annotation nextAnnotation = annotations[annotationIndex];
Class<? extends Annotation> class1 = nextAnnotation.annotationType(); Class<? extends Annotation> class1 = nextAnnotation.annotationType();
if (toFind.isAssignableFrom(class1)) { if (toFind.isAssignableFrom(class1)) {
return paramIndex; return paramIndex;
@ -191,10 +191,6 @@ public class ParameterUtil {
return null; return null;
} }
public static Integer findTagListParameterIndex(Method theMethod) {
return findParamAnnotationIndex(theMethod, TagListParam.class);
}
public static Object fromInteger(Class<?> theType, IntegerDt theArgument) { public static Object fromInteger(Class<?> theType, IntegerDt theArgument) {
if (theType.equals(Integer.class)) { if (theType.equals(Integer.class)) {
if (theArgument == null) { if (theArgument == null) {
@ -271,12 +267,8 @@ public class ParameterUtil {
}; };
} }
static List<String> splitParameterString(String theInput, boolean theUnescapeComponents) {
return splitParameterString(theInput, ',', theUnescapeComponents);
}
static List<String> splitParameterString(String theInput, char theDelimiter, boolean theUnescapeComponents) { static List<String> splitParameterString(String theInput, char theDelimiter, boolean theUnescapeComponents) {
ArrayList<String> retVal = new ArrayList<String>(); ArrayList<String> retVal = new ArrayList<>();
if (theInput != null) { if (theInput != null) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
for (int i = 0; i < theInput.length(); i++) { for (int i = 0; i < theInput.length(); i++) {
@ -335,7 +327,7 @@ public class ParameterUtil {
*/ */
public static String unescape(String theValue) { public static String unescape(String theValue) {
if (theValue == null) { if (theValue == null) {
return theValue; return null;
} }
if (theValue.indexOf('\\') == -1) { if (theValue.indexOf('\\') == -1) {
return theValue; return theValue;

View File

@ -176,7 +176,7 @@ public abstract class BaseJpaTest {
ourLog.info("Found {} results", size); ourLog.info("Found {} results", size);
List<IBaseResource> resources = theFound.getResources(0, size); List<IBaseResource> resources = theFound.getResources(0, size);
for (IBaseResource next : resources) { for (IBaseResource next : resources) {
retVal.add((IIdType) next.getIdElement().toUnqualifiedVersionless()); retVal.add(next.getIdElement().toUnqualifiedVersionless());
} }
return retVal; return retVal;
} }
@ -184,7 +184,7 @@ public abstract class BaseJpaTest {
protected List<IIdType> toUnqualifiedVersionlessIds(List<IBaseResource> theFound) { protected List<IIdType> toUnqualifiedVersionlessIds(List<IBaseResource> theFound) {
List<IIdType> retVal = new ArrayList<IIdType>(); List<IIdType> retVal = new ArrayList<IIdType>();
for (IBaseResource next : theFound) { for (IBaseResource next : theFound) {
retVal.add((IIdType) next.getIdElement().toUnqualifiedVersionless()); retVal.add(next.getIdElement().toUnqualifiedVersionless());
} }
return retVal; return retVal;
} }
@ -223,7 +223,7 @@ public abstract class BaseJpaTest {
} }
@AfterClass @AfterClass
public static void afterClassShutdownDerby() throws SQLException { public static void afterClassShutdownDerby() {
// DriverManager.getConnection("jdbc:derby:;shutdown=true"); // DriverManager.getConnection("jdbc:derby:;shutdown=true");
// try { // try {
// DriverManager.getConnection("jdbc:derby:memory:myUnitTestDB;drop=true"); // DriverManager.getConnection("jdbc:derby:memory:myUnitTestDB;drop=true");

View File

@ -48,118 +48,28 @@ import ca.uhn.fhir.validation.ResultSeverityEnum;
public class SystemProviderR4Test extends BaseJpaR4Test { public class SystemProviderR4Test extends BaseJpaR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderR4Test.class);
private static RestfulServer myRestServer; private static RestfulServer myRestServer;
private static IGenericClient ourClient; private static IGenericClient ourClient;
private static FhirContext ourCtx; private static FhirContext ourCtx;
private static CloseableHttpClient ourHttpClient; private static CloseableHttpClient ourHttpClient;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderR4Test.class);
private static Server ourServer; private static Server ourServer;
private static String ourServerBase; private static String ourServerBase;
private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor; private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor;
@Test @SuppressWarnings("deprecation")
public void testTransactionWithInlineConditionalUrl() throws Exception { @After
myDaoConfig.setAllowInlineMatchUrlReferences(true); public void after() {
myRestServer.setUseBrowserFriendlyContentTypes(true);
Patient p = new Patient(); ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
p.addName().setFamily("van de Heuvelcx85ioqWJbI").addGiven("Pietercx85ioqWJbI");
myPatientDao.create(p, mySrd);
Organization o = new Organization();
o.addIdentifier().setSystem("urn:oid:2.16.840.1.113883.2.4.6.1").setValue("07-8975469");
myOrganizationDao.create(o, mySrd);
//@formatter:off
String input = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
" <id value=\"20160113160203\"/>\n" +
" <type value=\"transaction\"/>\n" +
" <entry>\n" +
" <fullUrl value=\"urn:uuid:c72aa430-2ddc-456e-7a09-dea8264671d8\"/>\n" +
" <resource>\n" +
" <Encounter>\n" +
" <identifier>\n" +
" <use value=\"official\"/>\n" +
" <system value=\"http://healthcare.example.org/identifiers/encounter\"/>\n" +
" <value value=\"845962.8975469\"/>\n" +
" </identifier>\n" +
" <status value=\"in-progress\"/>\n" +
" <class value=\"inpatient\"/>\n" +
" <patient>\n" +
" <reference value=\"Patient?family=van%20de%20Heuvelcx85ioqWJbI&amp;given=Pietercx85ioqWJbI\"/>\n" +
" </patient>\n" +
" <serviceProvider>\n" +
" <reference value=\"Organization?identifier=urn:oid:2.16.840.1.113883.2.4.6.1|07-8975469\"/>\n" +
" </serviceProvider>\n" +
" </Encounter>\n" +
" </resource>\n" +
" <request>\n" +
" <method value=\"POST\"/>\n" +
" <url value=\"Encounter\"/>\n" +
" </request>\n" +
" </entry>\n" +
"</Bundle>";
//@formatter:off
HttpPost req = new HttpPost(ourServerBase);
req.setEntity(new StringEntity(input, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
CloseableHttpResponse resp = ourHttpClient.execute(req);
try {
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(encoded);
assertThat(encoded, containsString("transaction-response"));
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
} }
@Before
@Test public void before() {
public void testTransactionDeleteWithDuplicateDeletes() throws Exception { mySimpleHeaderInterceptor = new SimpleRequestHeaderInterceptor();
myDaoConfig.setAllowInlineMatchUrlReferences(true); ourClient.registerInterceptor(mySimpleHeaderInterceptor);
Patient p = new Patient();
p.addName().setFamily("van de Heuvelcx85ioqWJbI").addGiven("Pietercx85ioqWJbI");
IIdType id = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
ourClient.read().resource(Patient.class).withId(id);
Bundle inputBundle = new Bundle();
inputBundle.setType(BundleType.TRANSACTION);
inputBundle.addEntry().getRequest().setMethod(HTTPVerb.DELETE).setUrl(id.getValue());
inputBundle.addEntry().getRequest().setMethod(HTTPVerb.DELETE).setUrl(id.getValue());
inputBundle.addEntry().getRequest().setMethod(HTTPVerb.DELETE).setUrl("Patient?name=Pietercx85ioqWJbI");
String input = myFhirCtx.newXmlParser().encodeResourceToString(inputBundle);
HttpPost req = new HttpPost(ourServerBase + "?_pretty=true");
req.setEntity(new StringEntity(input, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
CloseableHttpResponse resp = ourHttpClient.execute(req);
try {
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(encoded);
assertThat(encoded, containsString("transaction-response"));
Bundle response = myFhirCtx.newXmlParser().parseResource(Bundle.class, encoded);
assertEquals(3, response.getEntry().size());
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
try {
ourClient.read().resource(Patient.class).withId(id).execute();
fail();
} catch (ResourceGoneException e) {
// good
}
} }
@Before @Before
public void beforeStartServer() throws Exception { public void beforeStartServer() throws Exception {
if (myRestServer == null) { if (myRestServer == null) {
@ -213,101 +123,6 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
myRestServer.setPagingProvider(myPagingProvider); myRestServer.setPagingProvider(myPagingProvider);
} }
@Before
public void before() {
mySimpleHeaderInterceptor = new SimpleRequestHeaderInterceptor();
ourClient.registerInterceptor(mySimpleHeaderInterceptor);
}
@SuppressWarnings("deprecation")
@After
public void after() {
myRestServer.setUseBrowserFriendlyContentTypes(true);
ourClient.unregisterInterceptor(mySimpleHeaderInterceptor);
}
@SuppressWarnings("deprecation")
@Test
public void testResponseUsesCorrectContentType() throws Exception {
myRestServer.setUseBrowserFriendlyContentTypes(true);
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
HttpGet get = new HttpGet(ourServerBase);
// get.addHeader("Accept", "application/xml, text/html");
CloseableHttpResponse http = ourHttpClient.execute(get);
assertThat(http.getFirstHeader("Content-Type").getValue(), containsString("application/fhir+json"));
}
/**
* FOrmat has changed, source is no longer valid
*/
@Test
@Ignore
public void testValidateUsingIncomingResources() throws Exception {
FhirInstanceValidator val = new FhirInstanceValidator(myValidationSupport);
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
interceptor.addValidatorModule(val);
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
interceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
myRestServer.registerInterceptor(interceptor);
try {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/questionnaire-sdc-profile-example-ussg-fht.xml");
String bundleStr = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
HttpPost req = new HttpPost(ourServerBase);
req.setEntity(new StringEntity(bundleStr, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
CloseableHttpResponse resp = ourHttpClient.execute(req);
try {
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(encoded);
//@formatter:off
assertThat(encoded, containsString("Questionnaire/54127-6/_history/"));
//@formatter:on
for (Header next : resp.getHeaders(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_NAME)) {
ourLog.info(next.toString());
}
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
} finally {
myRestServer.unregisterInterceptor(interceptor);
}
}
@Test
public void testEverythingReturnsCorrectFormatInPagingLink() throws Exception {
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
myRestServer.setPagingProvider(new FifoMemoryPagingProvider(1).setDefaultPageSize(10));
ResponseHighlighterInterceptor interceptor = new ResponseHighlighterInterceptor();
myRestServer.registerInterceptor(interceptor);
for (int i = 0; i < 11; i++) {
Patient p = new Patient();
p.addName().setFamily("Name" + i);
ourClient.create().resource(p).execute();
}
HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything");
get.addHeader("Accept", "application/xml, text/html");
CloseableHttpResponse http = ourHttpClient.execute(get);
try {
String response = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(response);
assertThat(response, containsString("_format=json"));
assertEquals(200, http.getStatusLine().getStatusCode());
} finally {
http.close();
}
myRestServer.unregisterInterceptor(interceptor);
}
@Test @Test
public void testEverythingReturnsCorrectBundleType() throws Exception { public void testEverythingReturnsCorrectBundleType() throws Exception {
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON); myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
@ -339,7 +154,36 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
myRestServer.unregisterInterceptor(interceptor); myRestServer.unregisterInterceptor(interceptor);
} }
@Test
public void testEverythingReturnsCorrectFormatInPagingLink() throws Exception {
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
myRestServer.setPagingProvider(new FifoMemoryPagingProvider(1).setDefaultPageSize(10));
ResponseHighlighterInterceptor interceptor = new ResponseHighlighterInterceptor();
myRestServer.registerInterceptor(interceptor);
for (int i = 0; i < 11; i++) {
Patient p = new Patient();
p.addName().setFamily("Name" + i);
ourClient.create().resource(p).execute();
}
HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything");
get.addHeader("Accept", "application/xml, text/html");
CloseableHttpResponse http = ourHttpClient.execute(get);
try {
String response = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(response);
assertThat(response, containsString("_format=json"));
assertEquals(200, http.getStatusLine().getStatusCode());
} finally {
http.close();
}
myRestServer.unregisterInterceptor(interceptor);
}
@Test @Test
public void testEverythingType() throws Exception { public void testEverythingType() throws Exception {
HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything"); HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything");
@ -350,6 +194,12 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
http.close(); http.close();
} }
} }
@Test
public void testGetOperationDefinition() {
OperationDefinition op = ourClient.read(OperationDefinition.class, "-s-get-resource-counts");
assertEquals("get-resource-counts", op.getCode());
}
@Test @Test
public void testMarkResourcesForReindexing() throws Exception { public void testMarkResourcesForReindexing() throws Exception {
@ -374,7 +224,19 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
} }
} }
@SuppressWarnings("deprecation")
@Test
public void testResponseUsesCorrectContentType() throws Exception {
myRestServer.setUseBrowserFriendlyContentTypes(true);
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
HttpGet get = new HttpGet(ourServerBase);
// get.addHeader("Accept", "application/xml, text/html");
CloseableHttpResponse http = ourHttpClient.execute(get);
assertThat(http.getFirstHeader("Content-Type").getValue(), containsString("application/fhir+json"));
}
@Transactional(propagation = Propagation.NEVER) @Transactional(propagation = Propagation.NEVER)
@Test @Test
public void testSuggestKeywords() throws Exception { public void testSuggestKeywords() throws Exception {
@ -458,11 +320,106 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
} }
} }
@Test
public void testTransactionCount() throws Exception {
for (int i = 0; i < 20; i++) {
Patient p = new Patient();
p.addName().setFamily("PATIENT_" + i);
myPatientDao.create(p, mySrd);
}
Bundle req = new Bundle();
req.setType(BundleType.TRANSACTION);
req.addEntry().getRequest().setMethod(HTTPVerb.GET).setUrl("Patient?_summary=count");
Bundle resp = ourClient.transaction().withBundle(req).execute();
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
assertEquals(1, resp.getEntry().size());
Bundle respSub = (Bundle) resp.getEntry().get(0).getResource();
assertEquals(20, respSub.getTotal());
assertEquals(0, respSub.getEntry().size());
}
@Test @Test
public void testGetOperationDefinition() { public void testTransactionCreateWithPreferHeader() throws Exception {
OperationDefinition op = ourClient.read(OperationDefinition.class, "-s-get-resource-counts");
assertEquals("get-resource-counts", op.getCode()); 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());
}
@Test
public void testTransactionDeleteWithDuplicateDeletes() throws Exception {
myDaoConfig.setAllowInlineMatchUrlReferences(true);
Patient p = new Patient();
p.addName().setFamily("van de Heuvelcx85ioqWJbI").addGiven("Pietercx85ioqWJbI");
IIdType id = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
ourClient.read().resource(Patient.class).withId(id);
Bundle inputBundle = new Bundle();
inputBundle.setType(BundleType.TRANSACTION);
inputBundle.addEntry().getRequest().setMethod(HTTPVerb.DELETE).setUrl(id.getValue());
inputBundle.addEntry().getRequest().setMethod(HTTPVerb.DELETE).setUrl(id.getValue());
inputBundle.addEntry().getRequest().setMethod(HTTPVerb.DELETE).setUrl("Patient?name=Pietercx85ioqWJbI");
String input = myFhirCtx.newXmlParser().encodeResourceToString(inputBundle);
HttpPost req = new HttpPost(ourServerBase + "?_pretty=true");
req.setEntity(new StringEntity(input, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
CloseableHttpResponse resp = ourHttpClient.execute(req);
try {
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(encoded);
assertThat(encoded, containsString("transaction-response"));
Bundle response = myFhirCtx.newXmlParser().parseResource(Bundle.class, encoded);
assertEquals(3, response.getEntry().size());
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
try {
ourClient.read().resource(Patient.class).withId(id).execute();
fail();
} catch (ResourceGoneException e) {
// good
}
} }
@Test @Test
@ -473,23 +430,6 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
ourLog.info(response); ourLog.info(response);
} }
@Test
public void testTransactionWithIncompleteBundle() throws Exception {
Patient patient = new Patient();
patient.setGender(AdministrativeGender.MALE);
Bundle bundle = new Bundle();
bundle.setType(BundleType.TRANSACTION);
bundle.addEntry().setResource(patient);
try {
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
fail();
} catch (InvalidRequestException e) {
assertThat(e.toString(), containsString("missing or invalid HTTP Verb"));
}
}
@Test @Test
public void testTransactionFromBundle2() throws Exception { public void testTransactionFromBundle2() throws Exception {
@ -607,61 +547,118 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
} }
@Test @Test
public void testTransactionCount() throws Exception { public void testTransactionWithIncompleteBundle() throws Exception {
for (int i = 0; i < 20; i++) { Patient patient = new Patient();
Patient p = new Patient(); patient.setGender(AdministrativeGender.MALE);
p.addName().setFamily("PATIENT_" + i);
myPatientDao.create(p, mySrd); Bundle bundle = new Bundle();
bundle.setType(BundleType.TRANSACTION);
bundle.addEntry().setResource(patient);
try {
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
fail();
} catch (InvalidRequestException e) {
assertThat(e.toString(), containsString("missing or invalid HTTP Verb"));
} }
Bundle req = new Bundle();
req.setType(BundleType.TRANSACTION);
req.addEntry().getRequest().setMethod(HTTPVerb.GET).setUrl("Patient?_summary=count");
Bundle resp = ourClient.transaction().withBundle(req).execute();
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
assertEquals(1, resp.getEntry().size());
Bundle respSub = (Bundle) resp.getEntry().get(0).getResource();
assertEquals(20, respSub.getTotal());
assertEquals(0, respSub.getEntry().size());
} }
@Test @Test
public void testTransactionCreateWithPreferHeader() throws Exception { public void testTransactionWithInlineConditionalUrl() throws Exception {
myDaoConfig.setAllowInlineMatchUrlReferences(true);
Patient p = new Patient(); Patient p = new Patient();
p.setActive(true); p.addName().setFamily("van de Heuvelcx85ioqWJbI").addGiven("Pietercx85ioqWJbI");
myPatientDao.create(p, mySrd);
Bundle req; Organization o = new Organization();
Bundle resp; o.addIdentifier().setSystem("urn:oid:2.16.840.1.113883.2.4.6.1").setValue("07-8975469");
myOrganizationDao.create(o, mySrd);
// 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 //@formatter:off
mySimpleHeaderInterceptor.setHeaderName(Constants.HEADER_PREFER); String input = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
mySimpleHeaderInterceptor.setHeaderValue(Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_MINIMAL); " <id value=\"20160113160203\"/>\n" +
req = new Bundle(); " <type value=\"transaction\"/>\n" +
req.setType(BundleType.TRANSACTION); " <entry>\n" +
req.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient"); " <fullUrl value=\"urn:uuid:c72aa430-2ddc-456e-7a09-dea8264671d8\"/>\n" +
resp = ourClient.transaction().withBundle(req).execute(); " <resource>\n" +
assertEquals(null, resp.getEntry().get(0).getResource()); " <Encounter>\n" +
assertEquals("201 Created", resp.getEntry().get(0).getResponse().getStatus()); " <identifier>\n" +
" <use value=\"official\"/>\n" +
// Prefer return=representation " <system value=\"http://healthcare.example.org/identifiers/encounter\"/>\n" +
mySimpleHeaderInterceptor.setHeaderName(Constants.HEADER_PREFER); " <value value=\"845962.8975469\"/>\n" +
mySimpleHeaderInterceptor.setHeaderValue(Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_REPRESENTATION); " </identifier>\n" +
req = new Bundle(); " <status value=\"in-progress\"/>\n" +
req.setType(BundleType.TRANSACTION); " <class value=\"inpatient\"/>\n" +
req.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient"); " <patient>\n" +
resp = ourClient.transaction().withBundle(req).execute(); " <reference value=\"Patient?family=van%20de%20Heuvelcx85ioqWJbI&amp;given=Pietercx85ioqWJbI\"/>\n" +
assertEquals(Patient.class, resp.getEntry().get(0).getResource().getClass()); " </patient>\n" +
assertEquals("201 Created", resp.getEntry().get(0).getResponse().getStatus()); " <serviceProvider>\n" +
" <reference value=\"Organization?identifier=urn:oid:2.16.840.1.113883.2.4.6.1|07-8975469\"/>\n" +
" </serviceProvider>\n" +
" </Encounter>\n" +
" </resource>\n" +
" <request>\n" +
" <method value=\"POST\"/>\n" +
" <url value=\"Encounter\"/>\n" +
" </request>\n" +
" </entry>\n" +
"</Bundle>";
//@formatter:off
HttpPost req = new HttpPost(ourServerBase);
req.setEntity(new StringEntity(input, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
CloseableHttpResponse resp = ourHttpClient.execute(req);
try {
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(encoded);
assertThat(encoded, containsString("transaction-response"));
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
}
/**
* FOrmat has changed, source is no longer valid
*/
@Test
@Ignore
public void testValidateUsingIncomingResources() throws Exception {
FhirInstanceValidator val = new FhirInstanceValidator(myValidationSupport);
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
interceptor.addValidatorModule(val);
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
interceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
myRestServer.registerInterceptor(interceptor);
try {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/questionnaire-sdc-profile-example-ussg-fht.xml");
String bundleStr = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
HttpPost req = new HttpPost(ourServerBase);
req.setEntity(new StringEntity(bundleStr, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
CloseableHttpResponse resp = ourHttpClient.execute(req);
try {
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(encoded);
//@formatter:off
assertThat(encoded, containsString("Questionnaire/54127-6/_history/"));
//@formatter:on
for (Header next : resp.getHeaders(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_NAME)) {
ourLog.info(next.toString());
}
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
} finally {
myRestServer.unregisterInterceptor(interceptor);
}
} }
@AfterClass @AfterClass

View File

@ -1,55 +0,0 @@
package ca.uhn.fhir.rest.server.method;
import java.io.IOException;
/*
* #%L
* HAPI FHIR - Server Framework
* %%
* Copyright (C) 2014 - 2018 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.lang.reflect.Method;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.AddTags;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IRestfulServer;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
class AddTagsMethodBinding extends BaseAddOrDeleteTagsMethodBinding {
public AddTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, AddTags theAnnotation) {
super(theMethod, theContext, theProvider, theAnnotation.type());
}
@Override
protected boolean isDelete() {
return false;
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.ADD_TAGS;
}
@Override
public Object invokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
return null;
}
}

View File

@ -1,117 +0,0 @@
package ca.uhn.fhir.rest.server.method;
/*-
* #%L
* HAPI FHIR - Server Framework
* %%
* Copyright (C) 2014 - 2018 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.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.TagListParam;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.server.IResourceProvider;
abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void> {
private Class<? extends IBaseResource> myType;
private Integer myIdParamIndex;
private String myResourceName;
private Integer myTagListParamIndex;
public BaseAddOrDeleteTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, Class<? extends IBaseResource> theTypeFromMethodAnnotation) {
super(theMethod, theContext, theProvider);
if (theProvider instanceof IResourceProvider) {
myType = ((IResourceProvider) theProvider).getResourceType();
} else {
myType = theTypeFromMethodAnnotation;
}
if (Modifier.isInterface(myType.getModifiers())) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not specify a resource type, but has an @" + IdParam.class.getSimpleName()
+ " parameter. Please specity a resource type in the method annotation on this method");
}
myResourceName = theContext.getResourceDefinition(myType).getName();
myIdParamIndex = ParameterUtil.findIdParameterIndex(theMethod, getContext());
myTagListParamIndex = ParameterUtil.findTagListParameterIndex(theMethod);
if (myIdParamIndex == null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not have an @" + IdParam.class.getSimpleName() + " parameter.");
}
if (myTagListParamIndex == null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not have a parameter of type " + TagList.class.getSimpleName() + ", or paramater is not annotated with the @"
+ TagListParam.class.getSimpleName() + " annotation");
}
}
@Override
public String getResourceName() {
return myResourceName;
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return null;
}
protected abstract boolean isDelete();
@Override
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (theRequest.getRequestType() != RequestTypeEnum.POST) {
return false;
}
if (!Constants.PARAM_TAGS.equals(theRequest.getOperation())) {
return false;
}
if (!myResourceName.equals(theRequest.getResourceName())) {
return false;
}
if (theRequest.getId() == null) {
return false;
}
if (isDelete()) {
if (Constants.PARAM_DELETE.equals(theRequest.getSecondaryOperation()) == false) {
return false;
}
} else {
if (theRequest.getSecondaryOperation() != null) {
return false;
}
}
return true;
}
}

View File

@ -494,10 +494,6 @@ public abstract class BaseMethodBinding<T> {
return new HistoryMethodBinding(theMethod, theContext, theProvider); return new HistoryMethodBinding(theMethod, theContext, theProvider);
} else if (validate != null) { } else if (validate != null) {
return new ValidateMethodBindingDstu2Plus(returnType, returnTypeFromRp, theMethod, theContext, theProvider, validate); return new ValidateMethodBindingDstu2Plus(returnType, returnTypeFromRp, theMethod, theContext, theProvider, validate);
} else if (addTags != null) {
return new AddTagsMethodBinding(theMethod, theContext, theProvider, addTags);
} else if (deleteTags != null) {
return new DeleteTagsMethodBinding(theMethod, theContext, theProvider, deleteTags);
} else if (transaction != null) { } else if (transaction != null) {
return new TransactionMethodBinding(theMethod, theContext, theProvider); return new TransactionMethodBinding(theMethod, theContext, theProvider);
} else if (operation != null) { } else if (operation != null) {

View File

@ -1,55 +0,0 @@
package ca.uhn.fhir.rest.server.method;
import java.io.IOException;
/*
* #%L
* HAPI FHIR - Server Framework
* %%
* Copyright (C) 2014 - 2018 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.lang.reflect.Method;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.DeleteTags;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IRestfulServer;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
public class DeleteTagsMethodBinding extends BaseAddOrDeleteTagsMethodBinding {
public DeleteTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, DeleteTags theDeleteTags) {
super(theMethod, theContext, theProvider, theDeleteTags.type());
}
@Override
protected boolean isDelete() {
return true;
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.DELETE_TAGS;
}
@Override
public Object invokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
return null;
}
}

View File

@ -49,6 +49,11 @@
if the stream.close() method threw an exception. Thanks to Carlos if the stream.close() method threw an exception. Thanks to Carlos
Eduardo Lara Augusto for investigating! Eduardo Lara Augusto for investigating!
</action> </action>
<action type="remove" issue="831">
The <![CDATA[<code>@TagListParam</code>]]> annotation has been removed. This
annotation had no use after DSTU1 but never got deleted and was misleading. Thanks
to Angelo Kastroulis for reporting!
</action>
</release> </release>
<release version="3.2.0" date="2018-01-13"> <release version="3.2.0" date="2018-01-13">
<action type="add"> <action type="add">