diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java index 63d2e0386c6..009302f15ba 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java @@ -21,7 +21,12 @@ package ca.uhn.fhir.rest.api; */ import java.nio.charset.Charset; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; public class Constants { @@ -109,6 +114,7 @@ public class Constants { public static final String HEADER_PREFER_RETURN = "return"; public static final String HEADER_PREFER_RETURN_MINIMAL = "minimal"; public static final String HEADER_PREFER_RETURN_REPRESENTATION = "representation"; + public static final String HEADER_PREFER_RETURN_OPERATION_OUTCOME = "OperationOutcome"; public static final String HEADER_SUFFIX_CT_UTF_8 = "; charset=UTF-8"; public static final String HEADERVALUE_CORS_ALLOW_METHODS_ALL = "GET, POST, PUT, DELETE, OPTIONS"; public static final Map HTTP_STATUS_NAMES; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/PreferReturnEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/PreferReturnEnum.java index 8f550867cf7..c9625bdf1b1 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/PreferReturnEnum.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/PreferReturnEnum.java @@ -27,7 +27,7 @@ import java.util.HashMap; */ public enum PreferReturnEnum { - REPRESENTATION("representation"), MINIMAL("minimal"); + REPRESENTATION("representation"), MINIMAL("minimal"), OPERATION_OUTCOME("OperationOutcome"); private String myHeaderValue; private static HashMap ourValues; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/StringClientParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/StringClientParam.java index 9aa120ff94f..5d0a463bbfe 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/StringClientParam.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/StringClientParam.java @@ -20,12 +20,12 @@ package ca.uhn.fhir.rest.gclient; * #L% */ +import ca.uhn.fhir.rest.api.Constants; +import org.hl7.fhir.instance.model.api.IPrimitiveType; + import java.util.Arrays; import java.util.List; -import ca.uhn.fhir.model.primitive.StringDt; -import ca.uhn.fhir.rest.api.Constants; - /** * * @author james @@ -59,6 +59,13 @@ public class StringClientParam extends BaseClientParam implements IParam { return new StringExactly(); } + /** + * The string contains given value + */ + public IStringMatch contains() { + return new StringContains(); + } + public interface IStringMatch { /** @@ -76,7 +83,7 @@ public class StringClientParam extends BaseClientParam implements IParam { /** * Requests that resources be returned which match the given value */ - ICriterion value(StringDt theValue); + ICriterion value(IPrimitiveType theValue); /** * Requests that resources be returned which match ANY of the given values (this is an OR search, not an AND search). Note that to @@ -90,17 +97,17 @@ public class StringClientParam extends BaseClientParam implements IParam { private class StringExactly implements IStringMatch { @Override public ICriterion value(String theValue) { - return new StringCriterion(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue); + return new StringCriterion<>(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue); } @Override - public ICriterion value(StringDt theValue) { - return new StringCriterion(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue.getValue()); + public ICriterion value(IPrimitiveType theValue) { + return new StringCriterion<>(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue.getValue()); } @Override public ICriterion values(List theValue) { - return new StringCriterion(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue); + return new StringCriterion<>(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue); } @Override @@ -109,20 +116,42 @@ public class StringClientParam extends BaseClientParam implements IParam { } } - private class StringMatches implements IStringMatch { + private class StringContains implements IStringMatch { @Override public ICriterion value(String theValue) { - return new StringCriterion(getParamName(), theValue); + return new StringCriterion<>(getParamName() + Constants.PARAMQUALIFIER_STRING_CONTAINS, theValue); } @Override - public ICriterion value(StringDt theValue) { - return new StringCriterion(getParamName(), theValue.getValue()); + public ICriterion value(IPrimitiveType theValue) { + return new StringCriterion<>(getParamName() + Constants.PARAMQUALIFIER_STRING_CONTAINS, theValue.getValue()); } @Override public ICriterion values(List theValue) { - return new StringCriterion(getParamName(), theValue); + return new StringCriterion<>(getParamName() + Constants.PARAMQUALIFIER_STRING_CONTAINS, theValue); + } + + @Override + public ICriterion values(String... theValues) { + return new StringCriterion(getParamName() + Constants.PARAMQUALIFIER_STRING_CONTAINS, Arrays.asList(theValues)); + } + } + + private class StringMatches implements IStringMatch { + @Override + public ICriterion value(String theValue) { + return new StringCriterion<>(getParamName(), theValue); + } + + @Override + public ICriterion value(IPrimitiveType theValue) { + return new StringCriterion<>(getParamName(), theValue.getValue()); + } + + @Override + public ICriterion values(List theValue) { + return new StringCriterion<>(getParamName(), theValue); } @Override diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/SearchParameter.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/SearchParameter.java index 930a3947c33..10423ae83da 100644 --- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/SearchParameter.java +++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/SearchParameter.java @@ -53,7 +53,7 @@ public class SearchParameter extends BaseQueryParameter { ourParamTypes.put(StringParam.class, RestSearchParameterTypeEnum.STRING); ourParamTypes.put(StringOrListParam.class, RestSearchParameterTypeEnum.STRING); ourParamTypes.put(StringAndListParam.class, RestSearchParameterTypeEnum.STRING); - ourParamQualifiers.put(RestSearchParameterTypeEnum.STRING, CollectionUtil.newSet(Constants.PARAMQUALIFIER_STRING_EXACT, Constants.PARAMQUALIFIER_MISSING, EMPTY_STRING)); + ourParamQualifiers.put(RestSearchParameterTypeEnum.STRING, CollectionUtil.newSet(Constants.PARAMQUALIFIER_STRING_EXACT, Constants.PARAMQUALIFIER_STRING_CONTAINS, Constants.PARAMQUALIFIER_MISSING, EMPTY_STRING)); ourParamTypes.put(UriParam.class, RestSearchParameterTypeEnum.URI); ourParamTypes.put(UriOrListParam.class, RestSearchParameterTypeEnum.URI); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java index c99071c9288..edfff44b128 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java @@ -1,5 +1,63 @@ package ca.uhn.fhir.jpa.provider; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsInRelativeOrder; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.hl7.fhir.instance.model.api.IBaseBundle; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.test.util.AopTestUtils; + +import com.google.common.base.Charsets; + import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; import ca.uhn.fhir.jpa.util.JpaConstants; @@ -11,46 +69,68 @@ import ca.uhn.fhir.model.dstu2.composite.CodingDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.composite.PeriodDt; import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; -import ca.uhn.fhir.model.dstu2.resource.*; +import ca.uhn.fhir.model.dstu2.resource.BaseResource; +import ca.uhn.fhir.model.dstu2.resource.Basic; +import ca.uhn.fhir.model.dstu2.resource.Binary; +import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; -import ca.uhn.fhir.model.dstu2.valueset.*; -import ca.uhn.fhir.model.primitive.*; +import ca.uhn.fhir.model.dstu2.resource.CarePlan; +import ca.uhn.fhir.model.dstu2.resource.Condition; +import ca.uhn.fhir.model.dstu2.resource.Device; +import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder; +import ca.uhn.fhir.model.dstu2.resource.DocumentManifest; +import ca.uhn.fhir.model.dstu2.resource.DocumentReference; +import ca.uhn.fhir.model.dstu2.resource.Encounter; +import ca.uhn.fhir.model.dstu2.resource.ImagingStudy; +import ca.uhn.fhir.model.dstu2.resource.Location; +import ca.uhn.fhir.model.dstu2.resource.Medication; +import ca.uhn.fhir.model.dstu2.resource.MedicationAdministration; +import ca.uhn.fhir.model.dstu2.resource.MedicationOrder; +import ca.uhn.fhir.model.dstu2.resource.MessageHeader; +import ca.uhn.fhir.model.dstu2.resource.Observation; +import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; +import ca.uhn.fhir.model.dstu2.resource.Organization; +import ca.uhn.fhir.model.dstu2.resource.Parameters; +import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.model.dstu2.resource.Practitioner; +import ca.uhn.fhir.model.dstu2.resource.Questionnaire; +import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse; +import ca.uhn.fhir.model.dstu2.resource.Subscription; +import ca.uhn.fhir.model.dstu2.resource.ValueSet; +import ca.uhn.fhir.model.dstu2.valueset.AnswerFormatEnum; +import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum; +import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum; +import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum; +import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; +import ca.uhn.fhir.model.dstu2.valueset.SearchEntryModeEnum; +import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum; +import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum; +import ca.uhn.fhir.model.primitive.DateDt; +import ca.uhn.fhir.model.primitive.DateTimeDt; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.model.primitive.InstantDt; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.model.primitive.UnsignedIntDt; +import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.SummaryEnum; import ca.uhn.fhir.rest.client.api.IGenericClient; -import ca.uhn.fhir.rest.param.*; -import ca.uhn.fhir.rest.server.exceptions.*; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.NumberParam; +import ca.uhn.fhir.rest.param.StringAndListParam; +import ca.uhn.fhir.rest.param.StringOrListParam; +import ca.uhn.fhir.rest.param.StringParam; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException; +import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; +import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.BundleUtil; import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.UrlUtil; -import com.google.common.base.Charsets; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.methods.*; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.hl7.fhir.instance.model.api.IBaseBundle; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.instance.model.api.IIdType; -import org.junit.*; -import org.springframework.test.util.AopTestUtils; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketTimeoutException; -import java.nio.charset.StandardCharsets; -import java.util.*; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { @@ -398,12 +478,35 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { } @Test - public void testCreateResourceReturnsOperationOutcomeByDefault() throws IOException { + public void testCreateResourceReturnsRepresentationByDefault() throws IOException { String resource = ""; HttpPost post = new HttpPost(ourServerBase + "/Patient"); post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); + CloseableHttpResponse response = ourHttpClient.execute(post); + try { + assertEquals(201, response.getStatusLine().getStatusCode()); + String respString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info(response.toString()); + ourLog.info(respString); + assertThat(respString, startsWith("")); + assertThat(respString, endsWith("")); + //assertThat(respString, containsString("")); + } finally { + response.getEntity().getContent().close(); + response.close(); + } + } + + @Test + public void testCreateResourceReturnsOperationOutcome() throws IOException { + String resource = ""; + + HttpPost post = new HttpPost(ourServerBase + "/Patient"); + post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); + post.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); + CloseableHttpResponse response = ourHttpClient.execute(post); try { assertEquals(201, response.getStatusLine().getStatusCode()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java index 0bb08f68358..c9df2834e90 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java @@ -1,7 +1,21 @@ package ca.uhn.fhir.jpa.provider.dstu3; import static org.apache.commons.lang3.StringUtils.isNotBlank; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsInRelativeOrder; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.Matchers.stringContainsInOrder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -10,57 +24,136 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.io.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; import java.math.BigDecimal; -import java.net.*; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; import java.nio.charset.StandardCharsets; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; -import ca.uhn.fhir.jpa.provider.r4.ResourceProviderR4Test; -import ca.uhn.fhir.rest.api.Constants; -import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.apache.http.NameValuePair; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.*; -import org.apache.http.entity.*; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicNameValuePair; import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator; -import org.hl7.fhir.dstu3.model.*; -import org.hl7.fhir.dstu3.model.Bundle.*; +import org.hl7.fhir.dstu3.model.AuditEvent; +import org.hl7.fhir.dstu3.model.BaseResource; +import org.hl7.fhir.dstu3.model.Basic; +import org.hl7.fhir.dstu3.model.Binary; +import org.hl7.fhir.dstu3.model.Bundle; +import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.dstu3.model.Bundle.BundleLinkComponent; +import org.hl7.fhir.dstu3.model.Bundle.BundleType; +import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb; +import org.hl7.fhir.dstu3.model.Bundle.SearchEntryMode; +import org.hl7.fhir.dstu3.model.CodeSystem; +import org.hl7.fhir.dstu3.model.CodeType; +import org.hl7.fhir.dstu3.model.Coding; +import org.hl7.fhir.dstu3.model.Condition; +import org.hl7.fhir.dstu3.model.DateTimeType; +import org.hl7.fhir.dstu3.model.DateType; +import org.hl7.fhir.dstu3.model.Device; +import org.hl7.fhir.dstu3.model.DocumentManifest; +import org.hl7.fhir.dstu3.model.DocumentReference; +import org.hl7.fhir.dstu3.model.Encounter; import org.hl7.fhir.dstu3.model.Encounter.EncounterLocationComponent; import org.hl7.fhir.dstu3.model.Encounter.EncounterStatus; import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender; +import org.hl7.fhir.dstu3.model.Extension; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.ImagingStudy; +import org.hl7.fhir.dstu3.model.InstantType; +import org.hl7.fhir.dstu3.model.IntegerType; +import org.hl7.fhir.dstu3.model.Location; +import org.hl7.fhir.dstu3.model.Medication; +import org.hl7.fhir.dstu3.model.MedicationAdministration; +import org.hl7.fhir.dstu3.model.MedicationRequest; +import org.hl7.fhir.dstu3.model.Meta; import org.hl7.fhir.dstu3.model.Narrative.NarrativeStatus; +import org.hl7.fhir.dstu3.model.Observation; import org.hl7.fhir.dstu3.model.Observation.ObservationStatus; +import org.hl7.fhir.dstu3.model.OperationOutcome; +import org.hl7.fhir.dstu3.model.Organization; +import org.hl7.fhir.dstu3.model.Parameters; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.Period; +import org.hl7.fhir.dstu3.model.Practitioner; +import org.hl7.fhir.dstu3.model.ProcedureRequest; +import org.hl7.fhir.dstu3.model.Quantity; +import org.hl7.fhir.dstu3.model.Questionnaire; import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType; +import org.hl7.fhir.dstu3.model.QuestionnaireResponse; +import org.hl7.fhir.dstu3.model.Reference; +import org.hl7.fhir.dstu3.model.StringType; +import org.hl7.fhir.dstu3.model.StructureDefinition; +import org.hl7.fhir.dstu3.model.Subscription; import org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType; import org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus; -import org.hl7.fhir.instance.model.api.*; -import org.junit.*; +import org.hl7.fhir.dstu3.model.UnsignedIntType; +import org.hl7.fhir.dstu3.model.ValueSet; +import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; import org.springframework.test.util.AopTestUtils; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; +import com.google.common.base.Charsets; import com.google.common.collect.Lists; import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.entity.Search; +import ca.uhn.fhir.jpa.provider.r4.ResourceProviderR4Test; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.StrictErrorHandler; +import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.SummaryEnum; +import ca.uhn.fhir.rest.client.api.IClientInterceptor; import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.IHttpRequest; +import ca.uhn.fhir.rest.client.api.IHttpResponse; import ca.uhn.fhir.rest.gclient.StringClientParam; -import ca.uhn.fhir.rest.param.*; -import ca.uhn.fhir.rest.server.exceptions.*; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.NumberParam; +import ca.uhn.fhir.rest.param.ParamPrefixEnum; +import ca.uhn.fhir.rest.param.StringAndListParam; +import ca.uhn.fhir.rest.param.StringOrListParam; +import ca.uhn.fhir.rest.param.StringParam; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; +import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.UrlUtil; @@ -397,12 +490,22 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { interceptor.setFailOnSeverity(null); ourRestServer.registerInterceptor(interceptor); + ourClient.registerInterceptor(new IClientInterceptor() { + @Override + public void interceptRequest(IHttpRequest theRequest) { + theRequest.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); + } + @Override + public void interceptResponse(IHttpResponse theResponse) throws IOException { // TODO Auto-generated method stu + } + + }); try { // Missing status, which is mandatory Observation obs = new Observation(); - obs.addIdentifier().setSystem("urn:foo").setValue("bar"); + obs.addIdentifier().setSystem("urn:foo").setValue("bar"); IBaseResource outcome = ourClient.create().resource(obs).execute().getOperationOutcome(); - + String encodedOo = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome); ourLog.info(encodedOo); assertThat(encodedOo, containsString("cvc-complex-type.2.4.b")); @@ -540,12 +643,34 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { } @Test - public void testCreateResourceReturnsOperationOutcomeByDefault() throws IOException { + public void testCreateResourceReturnsRepresentationByDefault() throws IOException { String resource = ""; HttpPost post = new HttpPost(ourServerBase + "/Patient"); post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); + CloseableHttpResponse response = ourHttpClient.execute(post); + try { + assertEquals(201, response.getStatusLine().getStatusCode()); + String respString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info(response.toString()); + ourLog.info(respString); + assertThat(respString, startsWith("")); + assertThat(respString, endsWith("")); + } finally { + response.getEntity().getContent().close(); + response.close(); + } + } + + @Test + public void testCreateResourceReturnsOperationOutcome() throws IOException { + String resource = ""; + + HttpPost post = new HttpPost(ourServerBase + "/Patient"); + post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); + post.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); + CloseableHttpResponse response = ourHttpClient.execute(post); try { assertEquals(201, response.getStatusLine().getStatusCode()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index 4e8c699d7d2..1b6bd81a6dd 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -1,39 +1,58 @@ package ca.uhn.fhir.jpa.provider.r4; -import ca.uhn.fhir.jpa.config.TestR4Config; -import ca.uhn.fhir.jpa.dao.DaoConfig; -import ca.uhn.fhir.jpa.entity.ResourceHistoryTable; -import ca.uhn.fhir.jpa.entity.Search; -import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; -import ca.uhn.fhir.jpa.util.JpaConstants; -import ca.uhn.fhir.util.StopWatch; -import ca.uhn.fhir.model.api.TemporalPrecisionEnum; -import ca.uhn.fhir.model.primitive.InstantDt; -import ca.uhn.fhir.model.primitive.UriDt; -import ca.uhn.fhir.parser.IParser; -import ca.uhn.fhir.parser.StrictErrorHandler; -import ca.uhn.fhir.rest.api.Constants; -import ca.uhn.fhir.rest.api.MethodOutcome; -import ca.uhn.fhir.rest.api.SummaryEnum; -import ca.uhn.fhir.rest.client.api.IGenericClient; -import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor; -import ca.uhn.fhir.rest.gclient.StringClientParam; -import ca.uhn.fhir.rest.param.*; -import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; -import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; -import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; -import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; -import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor; -import ca.uhn.fhir.util.TestUtil; -import ca.uhn.fhir.util.UrlUtil; -import com.google.common.base.Charsets; -import com.google.common.collect.Lists; +import static org.apache.commons.lang3.StringUtils.isNotBlank; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsInRelativeOrder; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.*; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; @@ -44,36 +63,111 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator; -import org.hl7.fhir.r4.model.*; -import org.hl7.fhir.r4.model.Bundle.*; +import org.hl7.fhir.r4.model.AuditEvent; +import org.hl7.fhir.r4.model.BaseResource; +import org.hl7.fhir.r4.model.Basic; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4.model.Bundle.BundleLinkComponent; +import org.hl7.fhir.r4.model.Bundle.BundleType; +import org.hl7.fhir.r4.model.Bundle.HTTPVerb; +import org.hl7.fhir.r4.model.Bundle.SearchEntryMode; +import org.hl7.fhir.r4.model.CarePlan; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.CodeType; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Condition; +import org.hl7.fhir.r4.model.DateTimeType; +import org.hl7.fhir.r4.model.DateType; +import org.hl7.fhir.r4.model.Device; +import org.hl7.fhir.r4.model.DocumentManifest; +import org.hl7.fhir.r4.model.DocumentReference; +import org.hl7.fhir.r4.model.Encounter; import org.hl7.fhir.r4.model.Encounter.EncounterLocationComponent; import org.hl7.fhir.r4.model.Encounter.EncounterStatus; import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.ImagingStudy; +import org.hl7.fhir.r4.model.ImmunizationRecommendation; +import org.hl7.fhir.r4.model.InstantType; +import org.hl7.fhir.r4.model.IntegerType; +import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.Medication; +import org.hl7.fhir.r4.model.MedicationAdministration; +import org.hl7.fhir.r4.model.MedicationRequest; +import org.hl7.fhir.r4.model.Meta; import org.hl7.fhir.r4.model.Narrative.NarrativeStatus; +import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Observation.ObservationStatus; +import org.hl7.fhir.r4.model.OperationOutcome; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Parameters; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Period; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.Quantity; +import org.hl7.fhir.r4.model.Questionnaire; import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemType; +import org.hl7.fhir.r4.model.QuestionnaireResponse; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ServiceRequest; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.model.Subscription; import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType; import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus; -import org.junit.*; +import org.hl7.fhir.r4.model.UnsignedIntType; +import org.hl7.fhir.r4.model.ValueSet; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; import org.springframework.test.util.AopTestUtils; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.math.BigDecimal; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketTimeoutException; -import java.nio.charset.StandardCharsets; -import java.util.*; +import com.google.common.base.Charsets; +import com.google.common.collect.Lists; -import static org.apache.commons.lang3.StringUtils.isNotBlank; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; +import ca.uhn.fhir.jpa.config.TestR4Config; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.entity.ResourceHistoryTable; +import ca.uhn.fhir.jpa.entity.Search; +import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; +import ca.uhn.fhir.jpa.util.JpaConstants; +import ca.uhn.fhir.model.api.TemporalPrecisionEnum; +import ca.uhn.fhir.model.primitive.InstantDt; +import ca.uhn.fhir.model.primitive.UriDt; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.StrictErrorHandler; +import ca.uhn.fhir.rest.api.Constants; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.api.SummaryEnum; +import ca.uhn.fhir.rest.client.api.IClientInterceptor; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.IHttpRequest; +import ca.uhn.fhir.rest.client.api.IHttpResponse; +import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor; +import ca.uhn.fhir.rest.gclient.StringClientParam; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.NumberParam; +import ca.uhn.fhir.rest.param.ParamPrefixEnum; +import ca.uhn.fhir.rest.param.StringAndListParam; +import ca.uhn.fhir.rest.param.StringOrListParam; +import ca.uhn.fhir.rest.param.StringParam; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; +import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor; +import ca.uhn.fhir.util.StopWatch; +import ca.uhn.fhir.util.TestUtil; +import ca.uhn.fhir.util.UrlUtil; public class ResourceProviderR4Test extends BaseResourceProviderR4Test { @@ -407,6 +501,16 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { interceptor.setFailOnSeverity(null); ourRestServer.registerInterceptor(interceptor); + myClient.registerInterceptor(new IClientInterceptor() { + @Override + public void interceptRequest(IHttpRequest theRequest) { + theRequest.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); + } + @Override + public void interceptResponse(IHttpResponse theResponse) throws IOException { // TODO Auto-generated method stu + } + + }); try { // Missing status, which is mandatory Observation obs = new Observation(); @@ -548,12 +652,34 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { } @Test - public void testCreateResourceReturnsOperationOutcomeByDefault() throws IOException { + public void testCreateResourceReturnsRepresentationByDefault() throws IOException { String resource = ""; HttpPost post = new HttpPost(ourServerBase + "/Patient"); post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); + CloseableHttpResponse response = ourHttpClient.execute(post); + try { + assertEquals(201, response.getStatusLine().getStatusCode()); + String respString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info(response.toString()); + ourLog.info(respString); + assertThat(respString, startsWith("")); + assertThat(respString, endsWith("")); + } finally { + response.getEntity().getContent().close(); + response.close(); + } + } + + @Test + public void testCreateResourceReturnsOperationOutcome() throws IOException { + String resource = ""; + + HttpPost post = new HttpPost(ourServerBase + "/Patient"); + post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); + post.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); + CloseableHttpResponse response = ourHttpClient.execute(post); try { assertEquals(201, response.getStatusLine().getStatusCode()); diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseOutcomeReturningMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseOutcomeReturningMethodBinding.java index ea92f5c5b79..cb1440f6415 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseOutcomeReturningMethodBinding.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseOutcomeReturningMethodBinding.java @@ -20,9 +20,29 @@ package ca.uhn.fhir.rest.server.method; * #L% */ + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; + import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.api.*; +import ca.uhn.fhir.rest.api.Constants; +import ca.uhn.fhir.rest.api.MethodOutcome; +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.api.SummaryEnum; import ca.uhn.fhir.rest.api.server.IRestfulResponse; import ca.uhn.fhir.rest.api.server.IRestfulServer; import ca.uhn.fhir.rest.api.server.RequestDetails; @@ -32,18 +52,6 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; -import org.apache.commons.lang3.StringUtils; -import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.instance.model.api.IIdType; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.EnumSet; -import java.util.Set; abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding { static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class); @@ -189,14 +197,20 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8"))); @@ -87,7 +103,7 @@ public class ServerMimetypeDstu2_1Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -125,6 +141,7 @@ public class ServerMimetypeDstu2_1Test { Patient p = new Patient(); p.addName().addFamily("FAMILY"); String enc = ourCtx.newXmlParser().encodeResourceToString(p); + String expectedResponseContent = ""; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML+ "; charset=utf-8"))); @@ -137,18 +154,20 @@ public class ServerMimetypeDstu2_1Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test - public void testCreateWithXmlNewWithAcceptHeader() throws Exception { + public void testCreateWithXmlNewWithAcceptHeaderReturnsOperationOutcome() throws Exception { Patient p = new Patient(); p.addName().addFamily("FAMILY"); String enc = ourCtx.newXmlParser().encodeResourceToString(p); + String expectedResponseContent = ""; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8"))); httpPost.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML); + httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); HttpResponse status = ourClient.execute(httpPost); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); @@ -158,7 +177,7 @@ public class ServerMimetypeDstu2_1Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -166,6 +185,7 @@ public class ServerMimetypeDstu2_1Test { Patient p = new Patient(); p.addName().addFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\"},\"name\":[{\"family\":[\"FAMILY\"]}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8"))); @@ -178,17 +198,19 @@ public class ServerMimetypeDstu2_1Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test - public void testCreateWithJsonNewNoAcceptHeader() throws Exception { + public void testCreateWithJsonNewNoAcceptHeaderReturnsOperationOutcome() throws Exception { Patient p = new Patient(); p.addName().addFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON+ "; charset=utf-8"))); + httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); HttpResponse status = ourClient.execute(httpPost); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); @@ -198,7 +220,7 @@ public class ServerMimetypeDstu2_1Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -206,6 +228,7 @@ public class ServerMimetypeDstu2_1Test { Patient p = new Patient(); p.addName().addFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\"},\"name\":[{\"family\":[\"FAMILY\"]}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8"))); @@ -219,7 +242,7 @@ public class ServerMimetypeDstu2_1Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -358,7 +381,9 @@ public class ServerMimetypeDstu2_1Test { public MethodOutcome create(@ResourceParam Patient theIdParam) { OperationOutcome oo = new OperationOutcome(); oo.addIssue().setDiagnostics(theIdParam.getName().get(0).getFamilyAsSingleString()); - return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(oo); + theIdParam.setId("1"); + theIdParam.getMeta().setVersionId("1"); + return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(oo).setResource(theIdParam); } @Override diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/PreferTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/PreferTest.java index 891bf2a9110..b7f87f0f2c6 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/PreferTest.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/PreferTest.java @@ -21,14 +21,20 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; -import org.junit.*; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.primitive.IdDt; -import ca.uhn.fhir.rest.annotation.*; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Update; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.util.PortUtil; @@ -54,6 +60,10 @@ public class PreferTest { Patient patient = new Patient(); patient.addIdentifier().setValue("002"); + + OperationOutcome oo = new OperationOutcome(); + oo.addIssue().setDiagnostics("DIAG"); + ourReturnOperationOutcome = oo; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_MINIMAL); @@ -76,7 +86,7 @@ public class PreferTest { } @Test - public void testCreatePreferMinimalWithOperationOutcome() throws Exception { + public void testCreatePreferOperationOutcomeWithOperationOutcome() throws Exception { OperationOutcome oo = new OperationOutcome(); oo.addIssue().setDiagnostics("DIAG"); @@ -86,7 +96,7 @@ public class PreferTest { patient.addIdentifier().setValue("002"); HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); - httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_MINIMAL); + httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); HttpResponse status = ourClient.execute(httpPost); @@ -123,7 +133,7 @@ public class PreferTest { assertEquals(Constants.STATUS_HTTP_201_CREATED, status.getStatusLine().getStatusCode()); assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), containsString(Constants.CT_FHIR_XML)); - assertEquals("", responseContent); + assertEquals("", responseContent); assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("location").getValue()); assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("content-location").getValue()); @@ -186,9 +196,8 @@ public class PreferTest { IdDt id = new IdDt("Patient/001/_history/002"); MethodOutcome retVal = new MethodOutcome(id); - Patient pt = new Patient(); - pt.setId(id); - retVal.setResource(pt); + thePatient.setId(id); + retVal.setResource(thePatient); retVal.setOperationOutcome(ourReturnOperationOutcome); @@ -205,9 +214,8 @@ public class PreferTest { IdDt id = new IdDt("Patient/001/_history/002"); MethodOutcome retVal = new MethodOutcome(id); - Patient pt = new Patient(); - pt.setId(id); - retVal.setResource(pt); + thePatient.setId(id); + retVal.setResource(thePatient); return retVal; } diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/UpdateDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/UpdateDstu2Test.java index a689ac321d9..2184c41c48b 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/UpdateDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/UpdateDstu2Test.java @@ -1,6 +1,8 @@ package ca.uhn.fhir.rest.server; -import static org.hamcrest.Matchers.blankOrNullString; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.text.IsEmptyString.emptyString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; @@ -22,14 +24,24 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; -import org.junit.*; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.dstu2.resource.Patient; -import ca.uhn.fhir.model.primitive.*; -import ca.uhn.fhir.rest.annotation.*; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.model.primitive.InstantDt; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.rest.annotation.ConditionalUrlParam; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.annotation.Update; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.util.PortUtil; @@ -113,7 +125,7 @@ public class UpdateDstu2Test { patient.setId("123"); patient.addIdentifier().setValue("002"); ourSetLastUpdated = new InstantDt("2002-04-22T11:22:33.022Z"); - + HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient/123"); httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); @@ -125,7 +137,12 @@ public class UpdateDstu2Test { ourLog.info("Response was:\n{}", responseContent); ourLog.info("Response was:\n{}", status); - assertThat(responseContent, blankOrNullString()); + assertThat(responseContent, is(not(emptyString()))); + + Patient actualPatient = (Patient) ourCtx.newXmlParser().parseResource(responseContent); + assertEquals(patient.getId().getIdPart(), actualPatient.getId().getIdPart()); + assertEquals(patient.getIdentifier().get(0).getValue(), actualPatient.getIdentifier().get(0).getValue()); + assertEquals(200, status.getStatusLine().getStatusCode()); assertEquals(null, status.getFirstHeader("location")); assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("content-location").getValue()); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/CreateDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/CreateDstu3Test.java index 1500193edc2..63913d53572 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/CreateDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/CreateDstu3Test.java @@ -36,7 +36,11 @@ import org.junit.BeforeClass; import org.junit.Test; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.annotation.*; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.Read; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Search; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.client.MyPatientWithExtensions; import ca.uhn.fhir.util.PortUtil; @@ -80,11 +84,12 @@ public class CreateDstu3Test { } @Test - public void testCreateReturnsOperationOutcome() throws Exception { + public void testCreateReturnsRepresentation() throws Exception { ourReturnOo = new OperationOutcome().addIssue(new OperationOutcomeIssueComponent().setDiagnostics("DIAG")); + String expectedResponseContent = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\"},\"gender\":\"male\"}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); - httpPost.setEntity(new StringEntity("{\"resourceType\":\"Patient\", \"status\":\"active\"}", ContentType.parse("application/fhir+json; charset=utf-8"))); + httpPost.setEntity(new StringEntity("{\"resourceType\":\"Patient\", \"gender\":\"male\"}", ContentType.parse("application/fhir+json; charset=utf-8"))); HttpResponse status = ourClient.execute(httpPost); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); @@ -93,8 +98,8 @@ public class CreateDstu3Test { ourLog.info("Response was:\n{}", responseContent); assertEquals(201, status.getStatusLine().getStatusCode()); + assertEquals(expectedResponseContent, responseContent); - assertThat(responseContent, containsString("DIAG")); } /** @@ -237,7 +242,10 @@ public class CreateDstu3Test { @Create() public MethodOutcome create(@ResourceParam Patient theIdParam) { - return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(ourReturnOo); + theIdParam.setId("1"); + theIdParam.getMeta().setVersionId("1"); + + return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(ourReturnOo).setResource(theIdParam); } @Override diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeDstu3Test.java index 9b8baffc83c..c1b49d09882 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeDstu3Test.java @@ -14,7 +14,11 @@ import java.util.concurrent.TimeUnit; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; -import org.apache.http.client.methods.*; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.methods.HttpTrace; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; @@ -23,12 +27,23 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; -import org.hl7.fhir.dstu3.model.*; +import org.hl7.fhir.dstu3.model.CapabilityStatement; +import org.hl7.fhir.dstu3.model.CodeType; +import org.hl7.fhir.dstu3.model.DateType; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.OperationOutcome; +import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.instance.model.api.IBaseResource; -import org.junit.*; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.annotation.*; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.Read; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Search; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.client.MyPatientWithExtensions; @@ -74,6 +89,7 @@ public class ServerMimetypeDstu3Test { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newXmlParser().encodeResourceToString(p); + String expectedResponseContent = ""; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8"))); @@ -86,7 +102,7 @@ public class ServerMimetypeDstu3Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -120,13 +136,15 @@ public class ServerMimetypeDstu3Test { } @Test - public void testCreateWithXmlNewNoAcceptHeader() throws Exception { + public void testCreateWithXmlNewNoAcceptHeaderReturnsOperationOutcome() throws Exception { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newXmlParser().encodeResourceToString(p); + String expectedResponseContent = ""; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML_NEW + "; charset=utf-8"))); + httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); HttpResponse status = ourClient.execute(httpPost); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); @@ -136,7 +154,7 @@ public class ServerMimetypeDstu3Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -144,6 +162,7 @@ public class ServerMimetypeDstu3Test { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newXmlParser().encodeResourceToString(p); + String expectedResponseContent = ""; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8"))); @@ -157,7 +176,7 @@ public class ServerMimetypeDstu3Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -165,6 +184,7 @@ public class ServerMimetypeDstu3Test { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\"},\"name\":[{\"family\":\"FAMILY\"}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8"))); @@ -177,7 +197,7 @@ public class ServerMimetypeDstu3Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -185,6 +205,7 @@ public class ServerMimetypeDstu3Test { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\"},\"name\":[{\"family\":\"FAMILY\"}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON_NEW + "; charset=utf-8"))); @@ -197,18 +218,20 @@ public class ServerMimetypeDstu3Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test - public void testCreateWithJsonNewWithAcceptHeader() throws Exception { + public void testCreateWithJsonNewWithAcceptHeaderReturnsOperationOutcome() throws Exception { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8"))); httpPost.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON_NEW); + httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); HttpResponse status = ourClient.execute(httpPost); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); @@ -218,7 +241,7 @@ public class ServerMimetypeDstu3Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -357,7 +380,9 @@ public class ServerMimetypeDstu3Test { public MethodOutcome create(@ResourceParam Patient theIdParam) { OperationOutcome oo = new OperationOutcome(); oo.addIssue().setDiagnostics(theIdParam.getNameFirstRep().getFamily()); - return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(oo); + theIdParam.setId("1"); + theIdParam.getMeta().setVersionId("1"); + return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(oo).setResource(theIdParam); } @Override diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java index 1acbbc3cc5e..e69852ead58 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java @@ -43,6 +43,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.nio.charset.Charset; +import java.util.Arrays; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.startsWith; @@ -1059,6 +1060,49 @@ public class GenericClientTest { } + @SuppressWarnings("unused") + @Test + public void testSearchByStringContains() throws Exception { + + String msg = getPatientFeedWithOneResult(); + + ArgumentCaptor 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_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(t-> new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"))); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Bundle response = client.search() + .forResource("Patient") + .where(Patient.NAME.contains().value("FOO")) + .returnBundle(Bundle.class) + .execute(); + assertEquals("http://example.com/fhir/Patient?name%3Acontains=FOO", capt.getValue().getURI().toString()); + + response = client.search() + .forResource("Patient") + .where(Patient.NAME.contains().values("FOO", "BAR")) + .returnBundle(Bundle.class) + .execute(); + assertEquals("http://example.com/fhir/Patient?name%3Acontains=FOO%2CBAR", capt.getValue().getURI().toString()); + + response = client.search() + .forResource("Patient") + .where(Patient.NAME.contains().values(Arrays.asList("FOO", "BAR"))) + .returnBundle(Bundle.class) + .execute(); + assertEquals("http://example.com/fhir/Patient?name%3Acontains=FOO%2CBAR", capt.getValue().getURI().toString()); + + response = client.search() + .forResource("Patient") + .where(Patient.NAME.contains().value(new StringType("FOO"))) + .returnBundle(Bundle.class) + .execute(); + assertEquals("http://example.com/fhir/Patient?name%3Acontains=FOO", capt.getValue().getURI().toString()); + } + @SuppressWarnings("unused") @Test public void testSearchByStringExact() throws Exception { diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/CreateR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/CreateR4Test.java index 571e86efdad..0ffdecb4d68 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/CreateR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/CreateR4Test.java @@ -1,11 +1,17 @@ package ca.uhn.fhir.rest.server; -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.annotation.*; -import ca.uhn.fhir.rest.api.MethodOutcome; -import ca.uhn.fhir.rest.client.MyPatientWithExtensions; -import ca.uhn.fhir.util.PortUtil; -import ca.uhn.fhir.util.TestUtil; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; @@ -30,13 +36,17 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.Read; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.Constants; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.client.MyPatientWithExtensions; +import ca.uhn.fhir.util.PortUtil; +import ca.uhn.fhir.util.TestUtil; public class CreateR4Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CreateR4Test.class); @@ -100,6 +110,7 @@ public class CreateR4Test { HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity("{\"resourceType\":\"Patient\", \"status\":\"active\"}", ContentType.parse("application/fhir+json; charset=utf-8"))); + httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); HttpResponse status = ourClient.execute(httpPost); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); @@ -111,6 +122,24 @@ public class CreateR4Test { assertThat(responseContent, containsString("DIAG")); } + + @Test + public void testCreateReturnsRepresentation() throws Exception { + ourReturnOo = new OperationOutcome().addIssue(new OperationOutcomeIssueComponent().setDiagnostics("DIAG")); + String expectedResponseContent = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\"},\"gender\":\"male\"}"; + + HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); + httpPost.setEntity(new StringEntity("{\"resourceType\":\"Patient\", \"gender\":\"male\"}", ContentType.parse("application/fhir+json; charset=utf-8"))); + HttpResponse status = ourClient.execute(httpPost); + + String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + IOUtils.closeQuietly(status.getEntity().getContent()); + + ourLog.info("Response was:\n{}", responseContent); + + assertEquals(201, status.getStatusLine().getStatusCode()); + assertEquals(expectedResponseContent, responseContent); + } @Test public void testCreateWithIncorrectContent1() throws Exception { @@ -253,7 +282,9 @@ public class CreateR4Test { @Create() public MethodOutcome create(@ResourceParam Patient theIdParam) { assertNull(theIdParam.getIdElement().getIdPart()); - return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(ourReturnOo); + theIdParam.setId("1"); + theIdParam.getMeta().setVersionId("1"); + return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(ourReturnOo).setResource(theIdParam); } @Override diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeR4Test.java index 98768af1279..f7f3edc2168 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeR4Test.java @@ -1,16 +1,25 @@ package ca.uhn.fhir.rest.server; -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.annotation.*; -import ca.uhn.fhir.rest.api.Constants; -import ca.uhn.fhir.rest.api.EncodingEnum; -import ca.uhn.fhir.rest.api.MethodOutcome; -import ca.uhn.fhir.rest.client.MyPatientWithExtensions; -import ca.uhn.fhir.util.PortUtil; -import ca.uhn.fhir.util.TestUtil; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; -import org.apache.http.client.methods.*; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.methods.HttpTrace; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; @@ -20,21 +29,29 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.r4.model.*; +import org.hl7.fhir.r4.model.CapabilityStatement; +import org.hl7.fhir.r4.model.CodeType; +import org.hl7.fhir.r4.model.DateType; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.OperationOutcome; +import org.hl7.fhir.r4.model.Patient; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.Read; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.Constants; +import ca.uhn.fhir.rest.api.EncodingEnum; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.client.MyPatientWithExtensions; +import ca.uhn.fhir.util.PortUtil; +import ca.uhn.fhir.util.TestUtil; public class ServerMimetypeR4Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerMimetypeR4Test.class); @@ -80,6 +97,7 @@ public class ServerMimetypeR4Test { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\"},\"name\":[{\"family\":\"FAMILY\"}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8"))); @@ -92,17 +110,19 @@ public class ServerMimetypeR4Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test - public void testCreateWithJsonNewNoAcceptHeader() throws Exception { + public void testCreateWithJsonNewNoAcceptHeaderReturnsOperationOutcome() throws Exception { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON_NEW + "; charset=utf-8"))); + httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); HttpResponse status = ourClient.execute(httpPost); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); @@ -112,7 +132,7 @@ public class ServerMimetypeR4Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -120,6 +140,7 @@ public class ServerMimetypeR4Test { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newJsonParser().encodeResourceToString(p); + String expectedResponseContent = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\"},\"name\":[{\"family\":\"FAMILY\"}]}"; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8"))); @@ -133,17 +154,19 @@ public class ServerMimetypeR4Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test - public void testCreateWithXmlLegacyNoAcceptHeader() throws Exception { + public void testCreateWithXmlLegacyNoAcceptHeaderReturnsOperationOutcome() throws Exception { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newXmlParser().encodeResourceToString(p); + String expectedResponseContent = ""; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8"))); + httpPost.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + "=" + Constants.HEADER_PREFER_RETURN_OPERATION_OUTCOME); HttpResponse status = ourClient.execute(httpPost); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); @@ -153,7 +176,7 @@ public class ServerMimetypeR4Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -161,6 +184,7 @@ public class ServerMimetypeR4Test { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newXmlParser().encodeResourceToString(p); + String expectedResponseContent = ""; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML_NEW + "; charset=utf-8"))); @@ -173,7 +197,7 @@ public class ServerMimetypeR4Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -181,6 +205,7 @@ public class ServerMimetypeR4Test { Patient p = new Patient(); p.addName().setFamily("FAMILY"); String enc = ourCtx.newXmlParser().encodeResourceToString(p); + String expectedResponseContent = ""; HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8"))); @@ -194,7 +219,7 @@ public class ServerMimetypeR4Test { assertEquals(201, status.getStatusLine().getStatusCode()); assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); - assertEquals("", responseContent); + assertEquals(expectedResponseContent, responseContent); } @Test @@ -416,7 +441,11 @@ public class ServerMimetypeR4Test { public MethodOutcome create(@ResourceParam Patient theIdParam) { OperationOutcome oo = new OperationOutcome(); oo.addIssue().setDiagnostics(theIdParam.getNameFirstRep().getFamily()); - return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(oo); + + theIdParam.setId("1"); + theIdParam.getMeta().setVersionId("1"); + + return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(oo).setResource(theIdParam); } @Override diff --git a/pom.xml b/pom.xml index a5cdc45ab4f..400b9180bc5 100644 --- a/pom.xml +++ b/pom.xml @@ -464,6 +464,10 @@ Frank Tao Smile CDR + + anamariaradu10 + Ana Maria Radu + diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 995fb40d82e..bfb533ad279 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -150,6 +150,19 @@ in order to prevent HTML injection attacks via maliciously crafted URLs. + + The generic/fluent client now supports the :contains modifier on + string search params. Thanks to Clayton Bodendein for the pull + request! + + + The HAPI FHIR Server has been updated to correctly reflect the current + FHIR specification behaviour for the Prefer header. This means that + the server will no longer return an OperationOutcome by default, but + that one may be requested via a Prefer header, using the newly implemented + "Repreentation: OperationOutcome" value. + Thanks to Ana Maria Radu for the pul request! +