From 2e4f80d7a3c6f03ab7fe177b4a9d96a57b169a21 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Fri, 26 Jan 2018 10:03:21 -0500 Subject: [PATCH] Fix #831 - Remove useless TagListParam annotation --- .../fhir/rest/annotation/TagListParam.java | 42 -- .../ca/uhn/fhir/rest/param/ParameterUtil.java | 60 +- .../java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java | 6 +- .../jpa/provider/r4/SystemProviderR4Test.java | 523 +++++++++--------- .../server/method/AddTagsMethodBinding.java | 55 -- .../BaseAddOrDeleteTagsMethodBinding.java | 117 ---- .../rest/server/method/BaseMethodBinding.java | 4 - .../method/DeleteTagsMethodBinding.java | 55 -- src/changes/changes.xml | 5 + 9 files changed, 294 insertions(+), 573 deletions(-) delete mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/TagListParam.java delete mode 100644 hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/AddTagsMethodBinding.java delete mode 100644 hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseAddOrDeleteTagsMethodBinding.java delete mode 100644 hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/DeleteTagsMethodBinding.java diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/TagListParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/TagListParam.java deleted file mode 100644 index 11bf3675296..00000000000 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/TagListParam.java +++ /dev/null @@ -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 -} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ParameterUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ParameterUtil.java index 6ff5cba7b73..0052885a40a 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ParameterUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ParameterUtil.java @@ -1,7 +1,28 @@ 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.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /* * #%L * HAPI FHIR - Core Library @@ -11,9 +32,9 @@ import java.lang.reflect.Method; * 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. @@ -21,29 +42,9 @@ import java.lang.reflect.Method; * limitations under the License. * #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 { - 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") public static T convertIdToType(IIdType value, Class theIdParamType) { if (value != null && !theIdParamType.isAssignableFrom(value.getClass())) { @@ -179,8 +180,7 @@ public class ParameterUtil { public static Integer findParamAnnotationIndex(Method theMethod, Class toFind) { int paramIndex = 0; for (Annotation[] annotations : theMethod.getParameterAnnotations()) { - for (int annotationIndex = 0; annotationIndex < annotations.length; annotationIndex++) { - Annotation nextAnnotation = annotations[annotationIndex]; + for (Annotation nextAnnotation : annotations) { Class class1 = nextAnnotation.annotationType(); if (toFind.isAssignableFrom(class1)) { return paramIndex; @@ -191,10 +191,6 @@ public class ParameterUtil { return null; } - public static Integer findTagListParameterIndex(Method theMethod) { - return findParamAnnotationIndex(theMethod, TagListParam.class); - } - public static Object fromInteger(Class theType, IntegerDt theArgument) { if (theType.equals(Integer.class)) { if (theArgument == null) { @@ -271,12 +267,8 @@ public class ParameterUtil { }; } - static List splitParameterString(String theInput, boolean theUnescapeComponents) { - return splitParameterString(theInput, ',', theUnescapeComponents); - } - static List splitParameterString(String theInput, char theDelimiter, boolean theUnescapeComponents) { - ArrayList retVal = new ArrayList(); + ArrayList retVal = new ArrayList<>(); if (theInput != null) { StringBuilder b = new StringBuilder(); for (int i = 0; i < theInput.length(); i++) { @@ -335,7 +327,7 @@ public class ParameterUtil { */ public static String unescape(String theValue) { if (theValue == null) { - return theValue; + return null; } if (theValue.indexOf('\\') == -1) { return theValue; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java index 5c285295a62..bca7e69e457 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java @@ -176,7 +176,7 @@ public abstract class BaseJpaTest { ourLog.info("Found {} results", size); List resources = theFound.getResources(0, size); for (IBaseResource next : resources) { - retVal.add((IIdType) next.getIdElement().toUnqualifiedVersionless()); + retVal.add(next.getIdElement().toUnqualifiedVersionless()); } return retVal; } @@ -184,7 +184,7 @@ public abstract class BaseJpaTest { protected List toUnqualifiedVersionlessIds(List theFound) { List retVal = new ArrayList(); for (IBaseResource next : theFound) { - retVal.add((IIdType) next.getIdElement().toUnqualifiedVersionless()); + retVal.add(next.getIdElement().toUnqualifiedVersionless()); } return retVal; } @@ -223,7 +223,7 @@ public abstract class BaseJpaTest { } @AfterClass - public static void afterClassShutdownDerby() throws SQLException { + public static void afterClassShutdownDerby() { // DriverManager.getConnection("jdbc:derby:;shutdown=true"); // try { // DriverManager.getConnection("jdbc:derby:memory:myUnitTestDB;drop=true"); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java index c00286c6825..aa3ce0dd9de 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java @@ -48,118 +48,28 @@ import ca.uhn.fhir.validation.ResultSeverityEnum; public class SystemProviderR4Test extends BaseJpaR4Test { + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderR4Test.class); private static RestfulServer myRestServer; private static IGenericClient ourClient; private static FhirContext ourCtx; private static CloseableHttpClient ourHttpClient; - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderR4Test.class); private static Server ourServer; private static String ourServerBase; private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor; - @Test - public void testTransactionWithInlineConditionalUrl() throws Exception { - myDaoConfig.setAllowInlineMatchUrlReferences(true); - - Patient p = new Patient(); - 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 = "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - ""; - //@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()); - } - + @SuppressWarnings("deprecation") + @After + public void after() { + myRestServer.setUseBrowserFriendlyContentTypes(true); + ourClient.unregisterInterceptor(mySimpleHeaderInterceptor); } - - @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 - } - + @Before + public void before() { + mySimpleHeaderInterceptor = new SimpleRequestHeaderInterceptor(); + ourClient.registerInterceptor(mySimpleHeaderInterceptor); } - @Before public void beforeStartServer() throws Exception { if (myRestServer == null) { @@ -213,101 +123,6 @@ public class SystemProviderR4Test extends BaseJpaR4Test { 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 public void testEverythingReturnsCorrectBundleType() throws Exception { myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON); @@ -339,7 +154,36 @@ public class SystemProviderR4Test extends BaseJpaR4Test { 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 public void testEverythingType() throws Exception { HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything"); @@ -350,6 +194,12 @@ public class SystemProviderR4Test extends BaseJpaR4Test { http.close(); } } + + @Test + public void testGetOperationDefinition() { + OperationDefinition op = ourClient.read(OperationDefinition.class, "-s-get-resource-counts"); + assertEquals("get-resource-counts", op.getCode()); + } @Test 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) @Test 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 - public void testGetOperationDefinition() { - OperationDefinition op = ourClient.read(OperationDefinition.class, "-s-get-resource-counts"); - assertEquals("get-resource-counts", op.getCode()); + 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()); + } + + @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 @@ -473,23 +430,6 @@ public class SystemProviderR4Test extends BaseJpaR4Test { 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 public void testTransactionFromBundle2() throws Exception { @@ -607,61 +547,118 @@ 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); + 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")); } - - 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 - public void testTransactionCreateWithPreferHeader() throws Exception { + public void testTransactionWithInlineConditionalUrl() throws Exception { + myDaoConfig.setAllowInlineMatchUrlReferences(true); Patient p = new Patient(); - p.setActive(true); + p.addName().setFamily("van de Heuvelcx85ioqWJbI").addGiven("Pietercx85ioqWJbI"); + myPatientDao.create(p, mySrd); - 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()); + 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); - // 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()); + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@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 diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/AddTagsMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/AddTagsMethodBinding.java deleted file mode 100644 index 4196c30db8a..00000000000 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/AddTagsMethodBinding.java +++ /dev/null @@ -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; - } - -} diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseAddOrDeleteTagsMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseAddOrDeleteTagsMethodBinding.java deleted file mode 100644 index fa25859573a..00000000000 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseAddOrDeleteTagsMethodBinding.java +++ /dev/null @@ -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 { - - private Class myType; - private Integer myIdParamIndex; - private String myResourceName; - private Integer myTagListParamIndex; - - public BaseAddOrDeleteTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, Class 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; - } - -} diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseMethodBinding.java index 0c156b41410..49246714eee 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseMethodBinding.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseMethodBinding.java @@ -494,10 +494,6 @@ public abstract class BaseMethodBinding { return new HistoryMethodBinding(theMethod, theContext, theProvider); } else if (validate != null) { 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) { return new TransactionMethodBinding(theMethod, theContext, theProvider); } else if (operation != null) { diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/DeleteTagsMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/DeleteTagsMethodBinding.java deleted file mode 100644 index 48dbd21631b..00000000000 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/DeleteTagsMethodBinding.java +++ /dev/null @@ -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; - } - -} diff --git a/src/changes/changes.xml b/src/changes/changes.xml index fbb3c23ae69..4de57232960 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,6 +49,11 @@ if the stream.close() method threw an exception. Thanks to Carlos Eduardo Lara Augusto for investigating! + + The @TagListParam]]> annotation has been removed. This + annotation had no use after DSTU1 but never got deleted and was misleading. Thanks + to Angelo Kastroulis for reporting! +