From b3d8d453de25d9690690c3c149a95dd5fb5b9555 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Sat, 18 Jun 2016 10:37:43 -0400 Subject: [PATCH] Improve test coverage and clean up UnclassifiedServerFailureException processing --- .../uhn/fhir/model/api/PathSpecification.java | 45 - .../ca/uhn/fhir/model/primitive/TimeDt.java | 1 + .../uhn/fhir/narrative/ThymeleafResolver.java | 55 - .../BaseOutcomeReturningMethodBinding.java | 2 +- .../BaseResourceReturningMethodBinding.java | 4 +- .../fhir/rest/method/IncludeParameter.java | 5 +- .../ca/uhn/fhir/rest/method/MethodUtil.java | 3 +- .../uhn/fhir/rest/method/SearchParameter.java | 4 - .../fhir/rest/param/QualifiedDateParam.java | 65 - .../fhir/rest/server/IRestfulResponse.java | 4 +- .../uhn/fhir/rest/server/RestfulResponse.java | 6 +- .../fhir/rest/server/RestfulServerUtils.java | 12 +- .../ExceptionHandlingInterceptor.java | 11 +- .../servlet/ServletRestfulResponse.java | 10 +- .../java/ca/uhn/fhir/validation/Problem.java | 35 - .../AbstractJaxRsConformanceProvider.java | 2 +- .../fhir/jaxrs/server/util/JaxRsResponse.java | 2 +- ...rceProviderQuestionnaireResponseDstu2.java | 29 - .../fhir/jpa/util/CustomNamingStrategy.java | 65 - .../jpa/util/HapiDerbyTenSevenDialect.java | 36 - .../ca/uhn/fhir/parser/XmlParserTest.java | 17 + ...a => ClientServerValidationDstu1Test.java} | 2 +- .../exceptions/ExceptionPropertiesTest.java | 3 + .../uhn/fhir/model/primitive/TimeDtTest.java | 15 + ...ThymeleafNarrativeGeneratorDstu2Test.java} | 4 +- ...a => ClientServerValidationDstu2Test.java} | 12 +- .../rest/client/GenericClientDstu3Test.java | 1222 +++++++++-------- .../fhir/rest/server/SearchSortDstu3Test.java | 5 - .../UnclassifiedServerExceptionDstu3Test.java | 110 ++ ...u3.java => SchemaValidationDstu3Test.java} | 11 +- src/changes/changes.xml | 18 + 31 files changed, 868 insertions(+), 947 deletions(-) delete mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/PathSpecification.java delete mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/narrative/ThymeleafResolver.java delete mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QualifiedDateParam.java delete mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/Problem.java delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderQuestionnaireResponseDstu2.java delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/CustomNamingStrategy.java delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/HapiDerbyTenSevenDialect.java rename hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/{ClientServerValidationTestDstu.java => ClientServerValidationDstu1Test.java} (99%) create mode 100644 hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/TimeDtTest.java rename hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/{DefaultThymeleafNarrativeGeneratorTestDstu2.java => DefaultThymeleafNarrativeGeneratorDstu2Test.java} (99%) rename hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/{ClientServerValidationTestDstu2.java => ClientServerValidationDstu2Test.java} (97%) create mode 100644 hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/UnclassifiedServerExceptionDstu3Test.java rename hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/{SchemaValidationTestDstu3.java => SchemaValidationDstu3Test.java} (86%) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/PathSpecification.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/PathSpecification.java deleted file mode 100644 index b22605a2170..00000000000 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/PathSpecification.java +++ /dev/null @@ -1,45 +0,0 @@ -package ca.uhn.fhir.model.api; - -import ca.uhn.fhir.util.CoverageIgnore; - -/* - * #%L - * HAPI FHIR - Core Library - * %% - * Copyright (C) 2014 - 2016 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% - */ - - -/** - * Represents a FHIR resource path specification, e.g. - * Patient.gender.coding - *

- * Note on equality: This class uses the {@link PathSpecification#setValue(String) value} - * as the single item used to provide {@link #hashCode()} and {@link #equals(Object)}. - *

- * - * @deprecated {@link Include} should be used instead - */ -@CoverageIgnore -@Deprecated -public class PathSpecification extends Include { - - public PathSpecification(String theInclude) { - super(theInclude); - } - - -} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/TimeDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/TimeDt.java index b761d9d3f37..b5c11540c3c 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/TimeDt.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/TimeDt.java @@ -52,6 +52,7 @@ public class TimeDt extends StringDt implements IQueryParameterType { */ @SimpleSetter public TimeDt(@SimpleSetter.Parameter(name = "theString") String theValue) { + this(); setValue(theValue); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/narrative/ThymeleafResolver.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/narrative/ThymeleafResolver.java deleted file mode 100644 index 365393dbd67..00000000000 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/narrative/ThymeleafResolver.java +++ /dev/null @@ -1,55 +0,0 @@ -package ca.uhn.fhir.narrative; - -/* - * #%L - * HAPI FHIR - Core Library - * %% - * Copyright (C) 2014 - 2016 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 org.thymeleaf.TemplateProcessingParameters; -import org.thymeleaf.templateresolver.ITemplateResolver; -import org.thymeleaf.templateresolver.TemplateResolution; - -public class ThymeleafResolver implements ITemplateResolver { - - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ThymeleafResolver.class); - - @Override - public String getName() { - return ""; - } - - @Override - public Integer getOrder() { - return 0; - } - - @Override - public void initialize() { - // nothing - } - - @Override - public TemplateResolution resolveTemplate(TemplateProcessingParameters theTemplateProcessingParameters) { - - String templateName = theTemplateProcessingParameters.getTemplateName(); - ourLog.info("Resolving template: {}", templateName); - - return null; - } - -} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java index 25cb667f936..59a22ff5e09 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java @@ -253,7 +253,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding summaryMode = Collections.emptySet(); - return restfulResponse.streamResponseAsResource(outcome, prettyPrint, summaryMode, operationStatus, theRequest.isRespondGzip(), true); + return restfulResponse.streamResponseAsResource(outcome, prettyPrint, summaryMode, operationStatus, null, theRequest.isRespondGzip(), true); // return theRequest.getResponse().returnResponse(ParseAction.create(outcome), operationStatus, allowPrefer, response, getResourceName()); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseResourceReturningMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseResourceReturningMethodBinding.java index 1bce71df52a..829195f5c7c 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseResourceReturningMethodBinding.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseResourceReturningMethodBinding.java @@ -260,8 +260,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest); - return theRequest.getResponse().streamResponseAsResource(responseObject.getResource(), prettyPrint, summaryMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), - isAddContentLocationHeader()); + return theRequest.getResponse().streamResponseAsResource(responseObject.getResource(), prettyPrint, summaryMode, Constants.STATUS_HTTP_200_OK, null, + theRequest.isRespondGzip(), isAddContentLocationHeader()); } else { // Is this request coming from a browser diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/IncludeParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/IncludeParameter.java index 3c33e152755..10cfae2c61a 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/IncludeParameter.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/IncludeParameter.java @@ -31,7 +31,6 @@ import java.util.TreeSet; import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.Include; -import ca.uhn.fhir.model.api.PathSpecification; import ca.uhn.fhir.rest.annotation.IncludeParam; import ca.uhn.fhir.rest.param.BaseQueryParameter; import ca.uhn.fhir.rest.server.Constants; @@ -60,7 +59,7 @@ class IncludeParameter extends BaseQueryParameter { } mySpecType = theSpecType; - if (mySpecType != Include.class && mySpecType != PathSpecification.class && mySpecType != String.class) { + if (mySpecType != Include.class && mySpecType != String.class) { throw new ConfigurationException("Invalid @" + IncludeParam.class.getSimpleName() + " parameter type: " + mySpecType); } @@ -72,7 +71,7 @@ class IncludeParameter extends BaseQueryParameter { ArrayList retVal = new ArrayList(); if (myInstantiableCollectionType == null) { - if (mySpecType == Include.class || mySpecType == PathSpecification.class) { + if (mySpecType == Include.class) { convertAndAddIncludeToList(retVal, (Include) theObject); } else { retVal.add(QualifiedParamList.singleton(((String) theObject))); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java index a2350ff976b..6f2b8a00b73 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java @@ -40,7 +40,6 @@ import ca.uhn.fhir.model.api.IQueryParameterOr; import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.Include; -import ca.uhn.fhir.model.api.PathSpecification; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.Tag; import ca.uhn.fhir.model.api.TagList; @@ -442,7 +441,7 @@ public class MethodUtil { if (parameterType == String.class) { instantiableCollectionType = null; specType = String.class; - } else if ((parameterType != Include.class && parameterType != PathSpecification.class) || innerCollectionType == null || outerCollectionType != null) { + } else if ((parameterType != Include.class) || innerCollectionType == null || outerCollectionType != null) { throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<" + Include.class.getSimpleName() + ">"); } else { instantiableCollectionType = (Class>) CollectionBinder.getInstantiableCollectionType(innerCollectionType, "Method '" + theMethod.getName() + "'"); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SearchParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SearchParameter.java index 74ef260db97..0dc52a23b97 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SearchParameter.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SearchParameter.java @@ -59,7 +59,6 @@ import ca.uhn.fhir.rest.param.HasParam; import ca.uhn.fhir.rest.param.NumberAndListParam; import ca.uhn.fhir.rest.param.NumberOrListParam; import ca.uhn.fhir.rest.param.NumberParam; -import ca.uhn.fhir.rest.param.QualifiedDateParam; import ca.uhn.fhir.rest.param.QuantityAndListParam; import ca.uhn.fhir.rest.param.QuantityOrListParam; import ca.uhn.fhir.rest.param.QuantityParam; @@ -81,7 +80,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.util.CollectionUtil; import ca.uhn.fhir.util.ReflectionUtil; -@SuppressWarnings("deprecation") public class SearchParameter extends BaseQueryParameter { private static final String EMPTY_STRING = ""; @@ -341,8 +339,6 @@ public class SearchParameter extends BaseQueryParameter { // ok } else if (StringDt.class.isAssignableFrom(type)) { myParamType = RestSearchParameterTypeEnum.STRING; - } else if (QualifiedDateParam.class.isAssignableFrom(type)) { - myParamType = RestSearchParameterTypeEnum.DATE; } else if (BaseIdentifierDt.class.isAssignableFrom(type)) { myParamType = RestSearchParameterTypeEnum.TOKEN; } else if (BaseQuantityDt.class.isAssignableFrom(type)) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QualifiedDateParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QualifiedDateParam.java deleted file mode 100644 index dc55d1b31a1..00000000000 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QualifiedDateParam.java +++ /dev/null @@ -1,65 +0,0 @@ -package ca.uhn.fhir.rest.param; - -/* - * #%L - * HAPI FHIR - Core Library - * %% - * Copyright (C) 2014 - 2016 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.util.Date; - -import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum; -import ca.uhn.fhir.util.CoverageIgnore; - -/** - * @deprecated Use {@link DateParam} instead (this class is identical, but was renamed to be less confusing) - */ -@Deprecated -@CoverageIgnore -public class QualifiedDateParam extends DateParam { - /** - * Constructor - */ - public QualifiedDateParam() { - } - - /** - * Constructor - */ - public QualifiedDateParam(QuantityCompararatorEnum theComparator, Date theDate) { - setComparator(theComparator); - setValue(theDate); - } - - /** - * Constructor - */ - public QualifiedDateParam(QuantityCompararatorEnum theComparator, String theDate) { - setComparator(theComparator); - setValueAsString(theDate); - } - - /** - * Constructor which takes a complete [qualifier]{date} string. - * - * @param theString The string - */ - public QualifiedDateParam(String theString) { - setValueAsQueryToken(null, theString); - } - -} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IRestfulResponse.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IRestfulResponse.java index fe0509e9f3e..8683baca9b0 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IRestfulResponse.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IRestfulResponse.java @@ -38,7 +38,7 @@ import ca.uhn.fhir.rest.method.ParseAction; public interface IRestfulResponse { - Object streamResponseAsResource(IBaseResource theActualResourceToReturn, boolean prettyPrint, Set summaryMode, int operationStatus, boolean respondGzip, boolean addContentLocationHeader) throws IOException; + Object streamResponseAsResource(IBaseResource theActualResourceToReturn, boolean thePrettyPrint, Set theSummaryMode, int theStatusCode, String theStatusMessage, boolean theRespondGzip, boolean theAddContentLocation) throws IOException; Object streamResponseAsBundle(Bundle bundle, Set summaryMode, boolean respondGzip, boolean requestIsBrowser) throws IOException; @@ -48,7 +48,7 @@ public interface IRestfulResponse { */ Object returnResponse(ParseAction outcome, int operationStatus, boolean allowPrefer, MethodOutcome response, String resourceName) throws IOException; - Writer getResponseWriter(int statusCode, String contentType, String charset, boolean respondGzip) throws UnsupportedEncodingException, IOException; + Writer getResponseWriter(int theStatusCode, String theStatusMessage, String theContentType, String theCharset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException; Object sendWriterResponse(int status, String contentType, String charset, Writer writer) throws IOException; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulResponse.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulResponse.java index 5fee3043aba..bb29626acec 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulResponse.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulResponse.java @@ -90,10 +90,10 @@ public abstract class RestfulResponse implements IRest } @Override - public final Object streamResponseAsResource(IBaseResource resource, boolean prettyPrint, Set summaryMode, - int statusCode, boolean respondGzip, boolean addContentLocationHeader) + public final Object streamResponseAsResource(IBaseResource theResource, boolean thePrettyPrint, Set theSummaryMode, + int theStatusCode, String theStatusMessage, boolean theRespondGzip, boolean theAddContentLocation) throws IOException { - return RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), resource, summaryMode, statusCode, addContentLocationHeader, respondGzip, getRequestDetails(), myOperationResourceId, myOperationResourceLastUpdated); + return RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), theResource, theSummaryMode, theStatusCode, theStatusMessage, theAddContentLocation, theRespondGzip, getRequestDetails(), myOperationResourceId, myOperationResourceLastUpdated); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java index fa911faa3bc..4e1c1717f35 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java @@ -537,7 +537,7 @@ public class RestfulServerUtils { String contentType = responseEncoding.getBundleContentType(); String charset = Constants.CHARSET_NAME_UTF8; - Writer writer = theRequestDetails.getResponse().getResponseWriter(status, contentType, charset, respondGzip); + Writer writer = theRequestDetails.getResponse().getResponseWriter(status, null, contentType, charset, respondGzip); try { IParser parser = RestfulServerUtils.getNewParser(theServer.getFhirContext(), theRequestDetails); @@ -552,11 +552,11 @@ public class RestfulServerUtils { } public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set theSummaryMode, int stausCode, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails) throws IOException { - return streamResponseAsResource(theServer, theResource, theSummaryMode, stausCode, theAddContentLocationHeader, respondGzip, theRequestDetails, null, null); + return streamResponseAsResource(theServer, theResource, theSummaryMode, stausCode, null, theAddContentLocationHeader, respondGzip, theRequestDetails, null, null); } - public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set theSummaryMode, int stausCode, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType theOperationResourceLastUpdated) throws IOException { + public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set theSummaryMode, int theStausCode, String theStatusMessage, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType theOperationResourceLastUpdated) throws IOException { IRestfulResponse restUtil = theRequestDetails.getResponse(); // Determine response encoding @@ -596,7 +596,7 @@ public class RestfulServerUtils { // malicious images or HTML blocks being served up as content. restUtil.addHeader(Constants.HEADER_CONTENT_DISPOSITION, "Attachment;"); - return restUtil.sendAttachmentResponse(bin, stausCode, contentType); + return restUtil.sendAttachmentResponse(bin, theStausCode, contentType); } // Ok, we're not serving a binary resource, so apply default encoding @@ -656,7 +656,7 @@ public class RestfulServerUtils { } String charset = Constants.CHARSET_NAME_UTF8; - Writer writer = restUtil.getResponseWriter(stausCode, contentType, charset, respondGzip); + Writer writer = restUtil.getResponseWriter(theStausCode, theStatusMessage, contentType, charset, respondGzip); if (theResource == null) { // No response is being returned } else if (encodingDomainResourceAsText && theResource instanceof IResource) { @@ -666,7 +666,7 @@ public class RestfulServerUtils { parser.encodeResourceToWriter(theResource, writer); } - return restUtil.sendWriterResponse(stausCode, contentType, charset, writer); + return restUtil.sendWriterResponse(theStausCode, contentType, charset, writer); } public static IIdType fullyQualifyResourceIdOrReturnNull(IRestfulServerDefaults theServer, IBaseResource theResource, String theServerBase, IIdType theResourceId) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptor.java index 8ca555595d7..f4661151f5d 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptor.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptor.java @@ -39,6 +39,7 @@ import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.IRestfulResponse; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException; import ca.uhn.fhir.util.OperationOutcomeUtil; public class ExceptionHandlingInterceptor extends InterceptorAdapter { @@ -79,7 +80,15 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter { } } - return response.streamResponseAsResource(oo, true, Collections.singleton(SummaryEnum.FALSE), statusCode, false, false); + String statusMessage = null; + if (theException instanceof UnclassifiedServerFailureException) { + String sm = theException.getMessage(); + if (isNotBlank(sm) && sm.indexOf('\n') == -1) { + statusMessage = sm; + } + } + + return response.streamResponseAsResource(oo, true, Collections.singleton(SummaryEnum.FALSE), statusCode, statusMessage, false, false); // theResponse.setStatus(statusCode); // theRequestDetails.getServer().addHeadersToResponse(theResponse); // theResponse.setContentType("text/plain"); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRestfulResponse.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRestfulResponse.java index ffbc8281481..668d4277bb1 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRestfulResponse.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRestfulResponse.java @@ -1,5 +1,7 @@ package ca.uhn.fhir.rest.server.servlet; +import static org.apache.commons.lang3.StringUtils.isNotBlank; + /* * #%L * HAPI FHIR - Core Library @@ -61,12 +63,12 @@ public class ServletRestfulResponse extends RestfulResponse summaryMode = Collections.emptySet(); - return (Response) response.streamResponseAsResource(conformance, false, summaryMode, Constants.STATUS_HTTP_200_OK, true, false); + return (Response) response.streamResponseAsResource(conformance, false, summaryMode, Constants.STATUS_HTTP_200_OK, null, true, false); } return (Response) response.returnResponse(null, Constants.STATUS_HTTP_500_INTERNAL_ERROR, true, null, getResourceType().getSimpleName()); } diff --git a/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/util/JaxRsResponse.java b/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/util/JaxRsResponse.java index c6b0a729fb0..5b1c0c32471 100644 --- a/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/util/JaxRsResponse.java +++ b/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/util/JaxRsResponse.java @@ -65,7 +65,7 @@ public class JaxRsResponse extends RestfulResponse { * by the server. */ @Override - public Writer getResponseWriter(int statusCode, String contentType, String charset, boolean respondGzip) + public Writer getResponseWriter(int theStatusCode, String theStatusMessage, String theContentType, String theCharset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException { return new StringWriter(); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderQuestionnaireResponseDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderQuestionnaireResponseDstu2.java deleted file mode 100644 index b42885adfb4..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderQuestionnaireResponseDstu2.java +++ /dev/null @@ -1,29 +0,0 @@ -package ca.uhn.fhir.jpa.provider; - -/* - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2016 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 ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse; - -public class BaseJpaResourceProviderQuestionnaireResponseDstu2 extends JpaResourceProviderDstu2 { - - // nothing yet - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/CustomNamingStrategy.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/CustomNamingStrategy.java deleted file mode 100644 index 2fe5cc1cd99..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/CustomNamingStrategy.java +++ /dev/null @@ -1,65 +0,0 @@ -package ca.uhn.fhir.jpa.util; - -/* - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2016 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 org.hibernate.cfg.ImprovedNamingStrategy; - -public class CustomNamingStrategy extends ImprovedNamingStrategy { - - private static final long serialVersionUID = 1L; - private static final String PREFIX = "FR_"; - -// @Override -// public String classToTableName(final String className) { -// return this.addPrefix(super.classToTableName(className)); -// } -// -// @Override -// public String collectionTableName(final String ownerEntity, -// final String ownerEntityTable, final String associatedEntity, -// final String associatedEntityTable, final String propertyName) { -// return this.addPrefix(super.collectionTableName(ownerEntity, -// ownerEntityTable, associatedEntity, associatedEntityTable, -// propertyName)); -// } -// -// @Override -// public String foreignKeyColumnName(String thePropertyName, String thePropertyEntityName, String thePropertyTableName, String theReferencedColumnName) { -// String foreignKeyColumnName = super.foreignKeyColumnName(thePropertyName, thePropertyEntityName, thePropertyTableName, theReferencedColumnName); -// return foreignKeyColumnName; -// } -// -// @Override -// public String logicalCollectionTableName(final String tableName, -// final String ownerEntityTable, final String associatedEntityTable, -// final String propertyName) { -// return this.addPrefix(super.logicalCollectionTableName(tableName, -// ownerEntityTable, associatedEntityTable, propertyName)); -// } -// -// private String addPrefix(final String composedTableName) { -// -// return PREFIX -// + composedTableName.toUpperCase().replace("_", ""); -// -// } - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/HapiDerbyTenSevenDialect.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/HapiDerbyTenSevenDialect.java deleted file mode 100644 index 8e45651122d..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/HapiDerbyTenSevenDialect.java +++ /dev/null @@ -1,36 +0,0 @@ -package ca.uhn.fhir.jpa.util; - -/* - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2016 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 org.hibernate.dialect.DerbyTenSevenDialect; - -/** - * As of Hibernate 5.0.1, DerbyTenSevenDialect doesn't seem to work when updating - * the schema, as it tries to create a duplicate schema - */ -public class HapiDerbyTenSevenDialect extends DerbyTenSevenDialect { - - @Override - public String getQuerySequencesString() { - return "select SEQUENCENAME from sys.syssequences"; - } - -} diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java index d56a5084f38..f7be2650868 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java @@ -44,6 +44,7 @@ import ca.uhn.fhir.model.dstu.composite.HumanNameDt; import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu.resource.AllergyIntolerance; import ca.uhn.fhir.model.dstu.resource.Binary; +import ca.uhn.fhir.model.dstu.resource.CarePlan; import ca.uhn.fhir.model.dstu.resource.Composition; import ca.uhn.fhir.model.dstu.resource.Condition; import ca.uhn.fhir.model.dstu.resource.Conformance; @@ -67,6 +68,7 @@ import ca.uhn.fhir.model.primitive.DateDt; import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.DecimalDt; import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.model.primitive.IdrefDt; import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; @@ -95,6 +97,21 @@ public class XmlParserTest { } + @Test + public void testEncodeAndParseIdref() { + CarePlan cp = new CarePlan(); + cp.addGoal().setNotes("Goal Notes").setElementSpecificId("goalId0"); + + IdrefDt idref = new IdrefDt(); + idref.setValue("#goalId0"); + idref.setTarget(cp); + idref.getTarget(); + cp.addActivity().getGoal().add(idref); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(cp); + ourLog.info(encoded); + } + /** * Test for #82 - Not yet enabled because the test won't pass */ diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationTestDstu.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationDstu1Test.java similarity index 99% rename from hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationTestDstu.java rename to hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationDstu1Test.java index 78ca4feb8bc..c4df0dcf03f 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationTestDstu.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationDstu1Test.java @@ -32,7 +32,7 @@ import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerExcept import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.util.TestUtil; -public class ClientServerValidationTestDstu { +public class ClientServerValidationDstu1Test { private FhirContext myCtx; private HttpClient myHttpClient; diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/exceptions/ExceptionPropertiesTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/exceptions/ExceptionPropertiesTest.java index 5c8cd54458a..a9887753cd8 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/exceptions/ExceptionPropertiesTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/exceptions/ExceptionPropertiesTest.java @@ -24,6 +24,9 @@ public class ExceptionPropertiesTest { new FhirClientConnectionException(new Exception()); new NotImplementedOperationException(""); new NotImplementedOperationException(null, new OperationOutcome()); + new FhirClientConnectionException(""); + new FhirClientConnectionException(new Exception()); + new FhirClientConnectionException("", new Exception()); } @SuppressWarnings("deprecation") diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/TimeDtTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/TimeDtTest.java new file mode 100644 index 00000000000..06383c56f74 --- /dev/null +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/TimeDtTest.java @@ -0,0 +1,15 @@ +package ca.uhn.fhir.model.primitive; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class TimeDtTest { + + @Test + public void testEncode() { + TimeDt dt = new TimeDt("11:33:01.123"); + assertEquals("11:33:01.123", dt.getValue()); + } + +} diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorTestDstu2.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorDstu2Test.java similarity index 99% rename from hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorTestDstu2.java rename to hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorDstu2Test.java index efc92ec448e..5cd631ee8aa 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorTestDstu2.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorDstu2Test.java @@ -37,9 +37,9 @@ import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.util.TestUtil; -public class DefaultThymeleafNarrativeGeneratorTestDstu2 { +public class DefaultThymeleafNarrativeGeneratorDstu2Test { private static FhirContext ourCtx = FhirContext.forDstu2(); - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultThymeleafNarrativeGeneratorTestDstu2.class); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultThymeleafNarrativeGeneratorDstu2Test.class); private DefaultThymeleafNarrativeGenerator myGen; @AfterClass diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationTestDstu2.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationDstu2Test.java similarity index 97% rename from hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationTestDstu2.java rename to hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationDstu2Test.java index 15dd008f31d..89a00e31bcd 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationTestDstu2.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ClientServerValidationDstu2Test.java @@ -1,7 +1,12 @@ package ca.uhn.fhir.rest.client; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +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 static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -32,16 +37,15 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.dstu2.resource.Conformance; import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.primitive.UriDt; -import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException; import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException; import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.util.TestUtil; -public class ClientServerValidationTestDstu2 { +public class ClientServerValidationDstu2Test { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ClientServerValidationTestDstu2.class); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ClientServerValidationDstu2Test.class); private FhirContext myCtx; private boolean myFirstResponse; private HttpClient myHttpClient; diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java index 6736a1fe1a4..bea6313966d 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java @@ -1,8 +1,6 @@ package ca.uhn.fhir.rest.client; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.either; -import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -16,7 +14,6 @@ import static org.mockito.Mockito.when; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; -import java.net.SocketTimeoutException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; @@ -68,11 +65,13 @@ import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.PreferReturnEnum; import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException; +import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException; import ca.uhn.fhir.rest.client.interceptor.CookieInterceptor; import ca.uhn.fhir.rest.client.interceptor.UserInfoInterceptor; import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException; +import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.VersionUtil; @@ -110,95 +109,6 @@ public class GenericClientDstu3Test { return body; } - @SuppressWarnings("deprecation") - @Test - public void testInvalidConformanceCall() { - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - try { - client.conformance(); - fail(); - } catch (IllegalArgumentException e) { - assertEquals("Must call fetchConformance() instead of conformance() for RI/STU3+ structures", e.getMessage()); - } - } - - @Test - public void testReadWithUnparseableResponse() throws Exception { - String msg = "{\"resourceTypeeeee\":\"Patient\"}"; - - 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_JSON + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"))); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - try { - client.read().resource("Patient").withId("123").elementsSubset("name", "identifier").execute(); - fail(); - } catch (FhirClientConnectionException e) { - assertEquals("Failed to parse response from server when performing GET to URL http://example.com/fhir/Patient/123?_elements=identifier%2Cname - ca.uhn.fhir.parser.DataFormatException: Invalid JSON content detected, missing required element: 'resourceType'", e.getMessage()); - } - } - - @Test - public void testHttp501() throws Exception { - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 501, "Not Implemented")); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { - @Override - public StringInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new StringInputStream("not implemented", Charsets.UTF_8); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - try { - client.read().resource(Patient.class).withId("1").execute(); - fail(); - } catch (NotImplementedOperationException e) { - assertEquals("HTTP 501 Not Implemented", e.getMessage()); - } - - } - - @SuppressWarnings("unchecked") - @Test - public void testClientFailures() throws Exception { - 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()).thenThrow(IllegalStateException.class, RuntimeException.class, Exception.class); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - try { - client.read().resource(Patient.class).withId("1").execute(); - fail(); - } catch (FhirClientConnectionException e) { - assertEquals("java.lang.IllegalStateException", e.getMessage()); - } - - try { - client.read().resource(Patient.class).withId("1").execute(); - fail(); - } catch (RuntimeException e) { - assertEquals("java.lang.RuntimeException", e.toString()); - } - - try { - client.read().resource(Patient.class).withId("1").execute(); - fail(); - } catch (FhirClientConnectionException e) { - assertEquals("java.lang.Exception", e.getMessage()); - } - } - @Test public void testBinaryCreateWithFhirContentType() throws Exception { IParser p = ourCtx.newXmlParser(); @@ -278,6 +188,67 @@ public class GenericClientDstu3Test { } + @SuppressWarnings("unchecked") + @Test + public void testClientFailures() throws Exception { + 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()).thenThrow(IllegalStateException.class, RuntimeException.class, Exception.class); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + try { + client.read().resource(Patient.class).withId("1").execute(); + fail(); + } catch (FhirClientConnectionException e) { + assertEquals("java.lang.IllegalStateException", e.getMessage()); + } + + try { + client.read().resource(Patient.class).withId("1").execute(); + fail(); + } catch (RuntimeException e) { + assertEquals("java.lang.RuntimeException", e.toString()); + } + + try { + client.read().resource(Patient.class).withId("1").execute(); + fail(); + } catch (FhirClientConnectionException e) { + assertEquals("java.lang.Exception", e.getMessage()); + } + } + + @Test + public void testCookieInterceptor() throws Exception { + final String respString = CustomTypeDstu3Test.createBundle(CustomTypeDstu3Test.createResource(false)); + 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(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + client.registerInterceptor(new CookieInterceptor("foo=bar")); + + //@formatter:off + Bundle resp = client + .history() + .onType(Patient.class) + .andReturnBundle(Bundle.class) + .execute(); + //@formatter:on + + assertEquals("foo=bar", capt.getAllValues().get(0).getFirstHeader("Cookie").getValue()); + } + @Test public void testCreateWithPreferRepresentationServerReturnsOO() throws Exception { final IParser p = ourCtx.newXmlParser(); @@ -370,61 +341,6 @@ public class GenericClientDstu3Test { assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(0).getURI().toASCIIString()); } - @Test - public void testUserInfoInterceptor() throws Exception { - final String respString = CustomTypeDstu3Test.createBundle(CustomTypeDstu3Test.createResource(false)); - 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(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - client.registerInterceptor(new UserInfoInterceptor("user_id", "user_name", "app-name")); - - //@formatter:off - Bundle resp = client - .history() - .onType(Patient.class) - .andReturnBundle(Bundle.class) - .execute(); - //@formatter:on - - } - - @Test - public void testCookieInterceptor() throws Exception { - final String respString = CustomTypeDstu3Test.createBundle(CustomTypeDstu3Test.createResource(false)); - 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(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - client.registerInterceptor(new CookieInterceptor("foo=bar")); - - //@formatter:off - Bundle resp = client - .history() - .onType(Patient.class) - .andReturnBundle(Bundle.class) - .execute(); - //@formatter:on - - assertEquals("foo=bar", capt.getAllValues().get(0).getFirstHeader("Cookie").getValue()); - } - @Test public void testExplicitCustomTypeHistoryType() throws Exception { final String respString = CustomTypeDstu3Test.createBundle(CustomTypeDstu3Test.createResource(false)); @@ -576,303 +492,6 @@ public class GenericClientDstu3Test { assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(0).getURI().toASCIIString()); } - @Test - public void testUpdateById() throws Exception { - IParser p = ourCtx.newXmlParser(); - - OperationOutcome conf = new OperationOutcome(); - conf.getText().setDivAsString("OK!"); - - final String respString = p.encodeResourceToString(conf); - 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(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - Patient pt = new Patient(); - pt.setId("222"); - pt.getText().setDivAsString("A PATIENT"); - - client.update().resource(pt).withId("111").execute(); - - ourLog.info(Arrays.asList(capt.getAllValues().get(0).getAllHeaders()).toString()); - - assertEquals("http://example.com/fhir/Patient/111", capt.getAllValues().get(0).getURI().toASCIIString()); - validateUserAgent(capt); - - assertEquals("application/xml+fhir;charset=utf-8", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue().toLowerCase().replace(" ", "")); - assertEquals(Constants.CT_FHIR_XML, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue()); - String body = extractBodyAsString(capt); - assertThat(body, containsString("")); - } - - @Test - public void testUpdateWithPreferRepresentationServerReturnsOO() throws Exception { - final IParser p = ourCtx.newXmlParser(); - - final OperationOutcome resp0 = new OperationOutcome(); - resp0.getText().setDivAsString("OK!"); - - final Patient resp1 = new Patient(); - resp1.getText().setDivAsString("FINAL VALUE"); - - 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.getAllHeaders()).thenAnswer(new Answer() { - @Override - public Header[] answer(InvocationOnMock theInvocation) throws Throwable { - return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") }; - } - }); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - if (myAnswerCount++ == 0) { - return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8")); - } else { - return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8")); - } - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - Patient pt = new Patient(); - pt.setId("Patient/222"); - pt.getText().setDivAsString("A PATIENT"); - - MethodOutcome outcome = client.update().resource(pt).prefer(PreferReturnEnum.REPRESENTATION).execute(); - - assertEquals(2, myAnswerCount); - assertNotNull(outcome.getOperationOutcome()); - assertNotNull(outcome.getResource()); - - assertEquals("
OK!
", ((OperationOutcome) outcome.getOperationOutcome()).getText().getDivAsString()); - assertEquals("
FINAL VALUE
", ((Patient) outcome.getResource()).getText().getDivAsString()); - - assertEquals(myAnswerCount, capt.getAllValues().size()); - assertEquals("http://example.com/fhir/Patient/222", capt.getAllValues().get(0).getURI().toASCIIString()); - assertEquals("http://foo.com/base/Patient/222/_history/3", capt.getAllValues().get(1).getURI().toASCIIString()); - } - - @Test - public void testValidate() throws Exception { - final IParser p = ourCtx.newXmlParser(); - - final OperationOutcome resp0 = new OperationOutcome(); - resp0.getText().setDivAsString("OK!"); - - 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.getAllHeaders()).thenAnswer(new Answer() { - @Override - public Header[] answer(InvocationOnMock theInvocation) throws Throwable { - return new Header[] {}; - } - }); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - Patient pt = new Patient(); - pt.setId("Patient/222"); - pt.getText().setDivAsString("A PATIENT"); - - MethodOutcome outcome = client.validate().resource(pt).execute(); - - assertNotNull(outcome.getOperationOutcome()); - assertEquals("
OK!
", ((OperationOutcome) outcome.getOperationOutcome()).getText().getDivAsString()); - - } - - @Test - public void testUpdateWithPreferRepresentationServerReturnsResource() throws Exception { - final IParser p = ourCtx.newXmlParser(); - - final Patient resp1 = new Patient(); - resp1.getText().setDivAsString("FINAL VALUE"); - - 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.getAllHeaders()).thenAnswer(new Answer() { - @Override - public Header[] answer(InvocationOnMock theInvocation) throws Throwable { - return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") }; - } - }); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - myAnswerCount++; - return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - Patient pt = new Patient(); - pt.setId("Patient/222"); - pt.getText().setDivAsString("A PATIENT"); - - MethodOutcome outcome = client.update().resource(pt).prefer(PreferReturnEnum.REPRESENTATION).execute(); - - assertEquals(1, myAnswerCount); - assertNull(outcome.getOperationOutcome()); - assertNotNull(outcome.getResource()); - - assertEquals("
FINAL VALUE
", ((Patient) outcome.getResource()).getText().getDivAsString()); - - assertEquals(myAnswerCount, capt.getAllValues().size()); - assertEquals("http://example.com/fhir/Patient/222", capt.getAllValues().get(0).getURI().toASCIIString()); - } - - @Test - public void testSearchForUnknownType() throws Exception { - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - try { - client.search(new UriDt("?aaaa")); - fail(); - } catch (IllegalArgumentException e) { - assertEquals("Unable to determine the resource type from the given URI: ?aaaa", e.getMessage()); - } - } - - @Test - public void testUserAgentForBinary() throws Exception { - IParser p = ourCtx.newXmlParser(); - - Conformance conf = new Conformance(); - conf.setCopyright("COPY"); - - final String respString = p.encodeResourceToString(conf); - 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(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - Binary bin = new Binary(); - bin.setContentType("application/foo"); - bin.setContent(new byte[] { 0, 1, 2, 3, 4 }); - client.create().resource(bin).execute(); - - ourLog.info(Arrays.asList(capt.getAllValues().get(0).getAllHeaders()).toString()); - - assertEquals("http://example.com/fhir/Binary", capt.getAllValues().get(0).getURI().toASCIIString()); - validateUserAgent(capt); - - assertEquals("application/foo", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue()); - assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue()); - assertArrayEquals(new byte[] { 0, 1, 2, 3, 4 }, extractBodyAsByteArray(capt)); - - } - - /** - * See #371 - */ - @Test - public void testSortDstu3Test() throws Exception { - IParser p = ourCtx.newXmlParser(); - - Bundle b = new Bundle(); - b.setType(BundleType.SEARCHSET); - - final String respString = p.encodeResourceToString(b); - 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(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - int idx = 0; - - //@formatter:off - client - .search() - .forResource(Patient.class) - .sort().ascending("address") - .returnBundle(Bundle.class) - .execute(); - assertEquals("http://example.com/fhir/Patient?_sort=address", capt.getAllValues().get(idx++).getURI().toASCIIString()); - - client - .search() - .forResource(Patient.class) - .sort().descending("address") - .returnBundle(Bundle.class) - .execute(); - assertEquals("http://example.com/fhir/Patient?_sort=-address", capt.getAllValues().get(idx++).getURI().toASCIIString()); - - client - .search() - .forResource(Patient.class) - .sort().descending("address") - .sort().ascending("name") - .sort().descending(Patient.BIRTHDATE) - .returnBundle(Bundle.class) - .execute(); - assertEquals("http://example.com/fhir/Patient?_sort=-address%2Cname%2C-birthdate", capt.getAllValues().get(idx++).getURI().toASCIIString()); - //@formatter:on - } - - @Test - public void testUserAgentForConformance() throws Exception { - IParser p = ourCtx.newXmlParser(); - - Conformance conf = new Conformance(); - conf.setCopyright("COPY"); - - final String respString = p.encodeResourceToString(conf); - 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(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - client.fetchConformance().ofType(Conformance.class).execute(); - assertEquals("http://example.com/fhir/metadata", capt.getAllValues().get(0).getURI().toASCIIString()); - validateUserAgent(capt); - } - @Test public void testForceConformance() throws Exception { final IParser p = ourCtx.newXmlParser(); @@ -922,25 +541,263 @@ public class GenericClientDstu3Test { assertEquals("http://testForceConformance.com/fhir/metadata", capt.getAllValues().get(3).getURI().toASCIIString()); } - private List> toTypeList(Class theClass) { - ArrayList> retVal = new ArrayList>(); - retVal.add(theClass); - return retVal; + @Test + public void testHttp499() throws Exception { + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 499, "Wacky Message")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public StringInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new StringInputStream("HELLO", Charsets.UTF_8); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + try { + client.read().resource(Patient.class).withId("1").execute(); + fail(); + } catch (UnclassifiedServerFailureException e) { + assertEquals("ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException: HTTP 499 Wacky Message", e.toString()); + assertEquals("HELLO", e.getResponseBody()); + } + } - private void validateUserAgent(ArgumentCaptor capt) { - assertEquals(1, capt.getAllValues().get(0).getHeaders("User-Agent").length); - assertEquals(expectedUserAgent(), capt.getAllValues().get(0).getHeaders("User-Agent")[0].getValue()); + @Test + public void testHttp501() throws Exception { + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 501, "Not Implemented")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public StringInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new StringInputStream("not implemented", Charsets.UTF_8); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + try { + client.read().resource(Patient.class).withId("1").execute(); + fail(); + } catch (NotImplementedOperationException e) { + assertEquals("HTTP 501 Not Implemented", e.getMessage()); + } + } - @AfterClass - public static void afterClassClearContext() { - TestUtil.clearAllStaticFieldsForUnitTest(); + @SuppressWarnings("deprecation") + @Test + public void testInvalidConformanceCall() { + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + try { + client.conformance(); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Must call fetchConformance() instead of conformance() for RI/STU3+ structures", e.getMessage()); + } } - @BeforeClass - public static void beforeClass() { - ourCtx = FhirContext.forDstu3(); + @Test + public void testReadWithUnparseableResponse() throws Exception { + String msg = "{\"resourceTypeeeee\":\"Patient\"}"; + + 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_JSON + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"))); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + try { + client.read().resource("Patient").withId("123").elementsSubset("name", "identifier").execute(); + fail(); + } catch (FhirClientConnectionException e) { + assertEquals("Failed to parse response from server when performing GET to URL http://example.com/fhir/Patient/123?_elements=identifier%2Cname - ca.uhn.fhir.parser.DataFormatException: Invalid JSON content detected, missing required element: 'resourceType'", e.getMessage()); + } + } + + @Test + public void testResponseHasContentTypeMissing() throws Exception { + IParser p = ourCtx.newXmlParser(); + Patient patient = new Patient(); + patient.addName().addFamily("FAM"); + final String respString = p.encodeResourceToString(patient); + + 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().getContentType()).thenReturn(null); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + try { + client.read().resource(Patient.class).withId("1").execute(); + fail(); + } catch (NonFhirResponseException e) { + assertEquals("Response contains no Content-Type", e.getMessage()); + } + + // Patient resp = client.read().resource(Patient.class).withId("1").execute(); + // assertEquals("FAM", resp.getNameFirstRep().getFamilyAsSingleString()); + } + + @Test + public void testResponseHasContentTypeNonFhir() throws Exception { + IParser p = ourCtx.newXmlParser(); + Patient patient = new Patient(); + patient.addName().addFamily("FAM"); + final String respString = p.encodeResourceToString(patient); + + 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", "text/plain")); + // when(myHttpResponse.getEntity().getContentType()).thenReturn(null); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + try { + client.read().resource(Patient.class).withId("1").execute(); + fail(); + } catch (NonFhirResponseException e) { + assertEquals("Response contains non FHIR Content-Type 'text/plain' : ", e.getMessage()); + } + + // Patient resp = client.read().resource(Patient.class).withId("1").execute(); + // assertEquals("FAM", resp.getNameFirstRep().getFamilyAsSingleString()); + } + + @Test + public void testSearchByDate() throws Exception { + final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}"; + + 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_JSON + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).then(new Answer() { + @Override + public InputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + int idx = 0; + + Date date = new DateTimeDt("2011-01-02T22:33:01Z").getValue(); + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.after().day("2011-01-02")) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient?birthdate=gt2011-01-02", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.after().day(date)) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient?birthdate=gt2011-01-02", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.afterOrEquals().day("2011-01-02")) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient?birthdate=ge2011-01-02", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.before().day("2011-01-02")) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient?birthdate=lt2011-01-02", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.beforeOrEquals().day("2011-01-02")) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient?birthdate=le2011-01-02", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.exactly().day("2011-01-02")) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient?birthdate=2011-01-02", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.after().second("2011-01-02T22:33:01Z")) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient?birthdate=gt2011-01-02T22:33:01Z", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString())); + idx++; + + String expDate = new DateTimeDt(date).getValueAsString(); + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.after().second(date)) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient?birthdate=gt" + expDate, UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString())); + idx++; + + //@formatter:off + client.search() + .forResource("Patient") + .where(Patient.BIRTHDATE.after().now()) + .returnBundle(Bundle.class) + .execute(); + //@formatter:on + assertThat(capt.getAllValues().get(idx).getURI().toString(), startsWith("http://example.com/fhir/Patient?birthdate=gt2")); + String dateString = UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()).substring(44); + ourLog.info(dateString); + assertEquals(TemporalPrecisionEnum.SECOND, new DateTimeDt(dateString).getPrecision()); + idx++; } @SuppressWarnings("deprecation") @@ -1084,47 +941,6 @@ public class GenericClientDstu3Test { } - @Test - public void testSearchByUrl() throws Exception { - final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}"; - - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).then(new Answer() { - @Override - public InputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - int idx = 0; - - //@formatter:off - client.search() - .forResource("Device") - .where(Device.URL.matches().value("http://foo.com")) - .returnBundle(Bundle.class) - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Device?url=http://foo.com", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString())); - assertEquals("http://example.com/fhir/Device?url=http%3A%2F%2Ffoo.com", capt.getAllValues().get(idx).getURI().toString()); - idx++; - - //@formatter:off - client.search() - .forResource("Device") - .where(Device.URL.matches().value(new StringDt("http://foo.com"))) - .returnBundle(Bundle.class) - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Device?url=http://foo.com", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString())); - idx++; - - } - @Test public void testSearchByString() throws Exception { final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}"; @@ -1226,7 +1042,7 @@ public class GenericClientDstu3Test { } @Test - public void testSearchByDate() throws Exception { + public void testSearchByUrl() throws Exception { final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}"; ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); @@ -1243,102 +1059,372 @@ public class GenericClientDstu3Test { IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); int idx = 0; - Date date = new DateTimeDt("2011-01-02T22:33:01Z").getValue(); - //@formatter:off client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.after().day("2011-01-02")) + .forResource("Device") + .where(Device.URL.matches().value("http://foo.com")) .returnBundle(Bundle.class) .execute(); //@formatter:on - assertEquals("http://example.com/fhir/Patient?birthdate=gt2011-01-02", capt.getAllValues().get(idx).getURI().toString()); + assertEquals("http://example.com/fhir/Device?url=http://foo.com", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString())); + assertEquals("http://example.com/fhir/Device?url=http%3A%2F%2Ffoo.com", capt.getAllValues().get(idx).getURI().toString()); idx++; //@formatter:off client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.after().day(date)) + .forResource("Device") + .where(Device.URL.matches().value(new StringDt("http://foo.com"))) .returnBundle(Bundle.class) .execute(); //@formatter:on - assertEquals("http://example.com/fhir/Patient?birthdate=gt2011-01-02", capt.getAllValues().get(idx).getURI().toString()); + assertEquals("http://example.com/fhir/Device?url=http://foo.com", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString())); idx++; + } + + @Test + public void testSearchForUnknownType() throws Exception { + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + try { + client.search(new UriDt("?aaaa")); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Unable to determine the resource type from the given URI: ?aaaa", e.getMessage()); + } + } + + /** + * See #371 + */ + @Test + public void testSortDstu3Test() throws Exception { + IParser p = ourCtx.newXmlParser(); + + Bundle b = new Bundle(); + b.setType(BundleType.SEARCHSET); + + final String respString = p.encodeResourceToString(b); + 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(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + int idx = 0; + //@formatter:off - client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.afterOrEquals().day("2011-01-02")) + client + .search() + .forResource(Patient.class) + .sort().ascending("address") .returnBundle(Bundle.class) .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient?birthdate=ge2011-01-02", capt.getAllValues().get(idx).getURI().toString()); - idx++; + assertEquals("http://example.com/fhir/Patient?_sort=address", capt.getAllValues().get(idx++).getURI().toASCIIString()); + + client + .search() + .forResource(Patient.class) + .sort().descending("address") + .returnBundle(Bundle.class) + .execute(); + assertEquals("http://example.com/fhir/Patient?_sort=-address", capt.getAllValues().get(idx++).getURI().toASCIIString()); + + client + .search() + .forResource(Patient.class) + .sort().descending("address") + .sort().ascending("name") + .sort().descending(Patient.BIRTHDATE) + .returnBundle(Bundle.class) + .execute(); + assertEquals("http://example.com/fhir/Patient?_sort=-address%2Cname%2C-birthdate", capt.getAllValues().get(idx++).getURI().toASCIIString()); + //@formatter:on + } + + @Test + public void testUpdateById() throws Exception { + IParser p = ourCtx.newXmlParser(); + + OperationOutcome conf = new OperationOutcome(); + conf.getText().setDivAsString("OK!"); + + final String respString = p.encodeResourceToString(conf); + 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(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Patient pt = new Patient(); + pt.setId("222"); + pt.getText().setDivAsString("A PATIENT"); + + client.update().resource(pt).withId("111").execute(); + + ourLog.info(Arrays.asList(capt.getAllValues().get(0).getAllHeaders()).toString()); + + assertEquals("http://example.com/fhir/Patient/111", capt.getAllValues().get(0).getURI().toASCIIString()); + validateUserAgent(capt); + + assertEquals("application/xml+fhir;charset=utf-8", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue().toLowerCase().replace(" ", "")); + assertEquals(Constants.CT_FHIR_XML, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue()); + String body = extractBodyAsString(capt); + assertThat(body, containsString("")); + } + + @Test + public void testUpdateWithPreferRepresentationServerReturnsOO() throws Exception { + final IParser p = ourCtx.newXmlParser(); + + final OperationOutcome resp0 = new OperationOutcome(); + resp0.getText().setDivAsString("OK!"); + + final Patient resp1 = new Patient(); + resp1.getText().setDivAsString("FINAL VALUE"); + + 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.getAllHeaders()).thenAnswer(new Answer() { + @Override + public Header[] answer(InvocationOnMock theInvocation) throws Throwable { + return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") }; + } + }); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + if (myAnswerCount++ == 0) { + return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8")); + } else { + return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8")); + } + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Patient pt = new Patient(); + pt.setId("Patient/222"); + pt.getText().setDivAsString("A PATIENT"); + + MethodOutcome outcome = client.update().resource(pt).prefer(PreferReturnEnum.REPRESENTATION).execute(); + + assertEquals(2, myAnswerCount); + assertNotNull(outcome.getOperationOutcome()); + assertNotNull(outcome.getResource()); + + assertEquals("
OK!
", ((OperationOutcome) outcome.getOperationOutcome()).getText().getDivAsString()); + assertEquals("
FINAL VALUE
", ((Patient) outcome.getResource()).getText().getDivAsString()); + + assertEquals(myAnswerCount, capt.getAllValues().size()); + assertEquals("http://example.com/fhir/Patient/222", capt.getAllValues().get(0).getURI().toASCIIString()); + assertEquals("http://foo.com/base/Patient/222/_history/3", capt.getAllValues().get(1).getURI().toASCIIString()); + } + + @Test + public void testUpdateWithPreferRepresentationServerReturnsResource() throws Exception { + final IParser p = ourCtx.newXmlParser(); + + final Patient resp1 = new Patient(); + resp1.getText().setDivAsString("FINAL VALUE"); + + 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.getAllHeaders()).thenAnswer(new Answer() { + @Override + public Header[] answer(InvocationOnMock theInvocation) throws Throwable { + return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") }; + } + }); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + myAnswerCount++; + return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Patient pt = new Patient(); + pt.setId("Patient/222"); + pt.getText().setDivAsString("A PATIENT"); + + MethodOutcome outcome = client.update().resource(pt).prefer(PreferReturnEnum.REPRESENTATION).execute(); + + assertEquals(1, myAnswerCount); + assertNull(outcome.getOperationOutcome()); + assertNotNull(outcome.getResource()); + + assertEquals("
FINAL VALUE
", ((Patient) outcome.getResource()).getText().getDivAsString()); + + assertEquals(myAnswerCount, capt.getAllValues().size()); + assertEquals("http://example.com/fhir/Patient/222", capt.getAllValues().get(0).getURI().toASCIIString()); + } + + @Test + public void testUserAgentForBinary() throws Exception { + IParser p = ourCtx.newXmlParser(); + + Conformance conf = new Conformance(); + conf.setCopyright("COPY"); + + final String respString = p.encodeResourceToString(conf); + 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(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Binary bin = new Binary(); + bin.setContentType("application/foo"); + bin.setContent(new byte[] { 0, 1, 2, 3, 4 }); + client.create().resource(bin).execute(); + + ourLog.info(Arrays.asList(capt.getAllValues().get(0).getAllHeaders()).toString()); + + assertEquals("http://example.com/fhir/Binary", capt.getAllValues().get(0).getURI().toASCIIString()); + validateUserAgent(capt); + + assertEquals("application/foo", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue()); + assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue()); + assertArrayEquals(new byte[] { 0, 1, 2, 3, 4 }, extractBodyAsByteArray(capt)); + + } + + @Test + public void testUserAgentForConformance() throws Exception { + IParser p = ourCtx.newXmlParser(); + + Conformance conf = new Conformance(); + conf.setCopyright("COPY"); + + final String respString = p.encodeResourceToString(conf); + 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(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + client.fetchConformance().ofType(Conformance.class).execute(); + assertEquals("http://example.com/fhir/metadata", capt.getAllValues().get(0).getURI().toASCIIString()); + validateUserAgent(capt); + } + + @Test + public void testUserInfoInterceptor() throws Exception { + final String respString = CustomTypeDstu3Test.createBundle(CustomTypeDstu3Test.createResource(false)); + 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(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + client.registerInterceptor(new UserInfoInterceptor("user_id", "user_name", "app-name")); //@formatter:off - client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.before().day("2011-01-02")) - .returnBundle(Bundle.class) + Bundle resp = client + .history() + .onType(Patient.class) + .andReturnBundle(Bundle.class) .execute(); //@formatter:on - assertEquals("http://example.com/fhir/Patient?birthdate=lt2011-01-02", capt.getAllValues().get(idx).getURI().toString()); - idx++; - //@formatter:off - client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.beforeOrEquals().day("2011-01-02")) - .returnBundle(Bundle.class) - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient?birthdate=le2011-01-02", capt.getAllValues().get(idx).getURI().toString()); - idx++; + } - //@formatter:off - client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.exactly().day("2011-01-02")) - .returnBundle(Bundle.class) - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient?birthdate=2011-01-02", capt.getAllValues().get(idx).getURI().toString()); - idx++; + @Test + public void testValidate() throws Exception { + final IParser p = ourCtx.newXmlParser(); - //@formatter:off - client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.after().second("2011-01-02T22:33:01Z")) - .returnBundle(Bundle.class) - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient?birthdate=gt2011-01-02T22:33:01Z", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString())); - idx++; + final OperationOutcome resp0 = new OperationOutcome(); + resp0.getText().setDivAsString("OK!"); - String expDate = new DateTimeDt(date).getValueAsString(); + 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.getAllHeaders()).thenAnswer(new Answer() { + @Override + public Header[] answer(InvocationOnMock theInvocation) throws Throwable { + return new Header[] {}; + } + }); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8")); + } + }); - //@formatter:off - client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.after().second(date)) - .returnBundle(Bundle.class) - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient?birthdate=gt" + expDate, UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString())); - idx++; + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - //@formatter:off - client.search() - .forResource("Patient") - .where(Patient.BIRTHDATE.after().now()) - .returnBundle(Bundle.class) - .execute(); - //@formatter:on - assertThat(capt.getAllValues().get(idx).getURI().toString(), startsWith("http://example.com/fhir/Patient?birthdate=gt2")); - String dateString = UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()).substring(44); - ourLog.info(dateString); - assertEquals(TemporalPrecisionEnum.SECOND, new DateTimeDt(dateString).getPrecision()); - idx++; + Patient pt = new Patient(); + pt.setId("Patient/222"); + pt.getText().setDivAsString("A PATIENT"); + + MethodOutcome outcome = client.validate().resource(pt).execute(); + + assertNotNull(outcome.getOperationOutcome()); + assertEquals("
OK!
", ((OperationOutcome) outcome.getOperationOutcome()).getText().getDivAsString()); + + } + + private List> toTypeList(Class theClass) { + ArrayList> retVal = new ArrayList>(); + retVal.add(theClass); + return retVal; + } + + private void validateUserAgent(ArgumentCaptor capt) { + assertEquals(1, capt.getAllValues().get(0).getHeaders("User-Agent").length); + assertEquals(expectedUserAgent(), capt.getAllValues().get(0).getHeaders("User-Agent")[0].getValue()); + } + + @AfterClass + public static void afterClassClearContext() { + TestUtil.clearAllStaticFieldsForUnitTest(); + } + + @BeforeClass + public static void beforeClass() { + ourCtx = FhirContext.forDstu3(); } } diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/SearchSortDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/SearchSortDstu3Test.java index 9cc7e983b64..1fe1fefb4ac 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/SearchSortDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/SearchSortDstu3Test.java @@ -1,8 +1,6 @@ package ca.uhn.fhir.rest.server; -import static org.hamcrest.Matchers.stringContainsInOrder; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.List; @@ -26,13 +24,10 @@ import org.junit.BeforeClass; import org.junit.Test; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.annotation.Count; -import ca.uhn.fhir.rest.annotation.OptionalParam; import ca.uhn.fhir.rest.annotation.Search; import ca.uhn.fhir.rest.annotation.Sort; import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortSpec; -import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.util.PortUtil; import ca.uhn.fhir.util.TestUtil; diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/UnclassifiedServerExceptionDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/UnclassifiedServerExceptionDstu3Test.java new file mode 100644 index 00000000000..be4aa920776 --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/UnclassifiedServerExceptionDstu3Test.java @@ -0,0 +1,110 @@ +package ca.uhn.fhir.rest.server; + +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.hl7.fhir.dstu3.model.OperationOutcome; +import org.hl7.fhir.dstu3.model.OperationOutcome.IssueType; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.instance.model.api.IBaseResource; +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.rest.annotation.Search; +import ca.uhn.fhir.rest.api.SortSpec; +import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException; +import ca.uhn.fhir.util.PortUtil; +import ca.uhn.fhir.util.TestUtil; + +public class UnclassifiedServerExceptionDstu3Test { + + private static CloseableHttpClient ourClient; + private static FhirContext ourCtx = FhirContext.forDstu3(); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(UnclassifiedServerExceptionDstu3Test.class); + private static int ourPort; + private static Server ourServer; + public static UnclassifiedServerFailureException ourException; + + @Test + public void testSearch() throws Exception { + + OperationOutcome operationOutcome = new OperationOutcome(); + operationOutcome.addIssue().setCode(IssueType.BUSINESSRULE); + ourException = new UnclassifiedServerFailureException(477, "SOME MESSAGE", operationOutcome); + + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient"); + CloseableHttpResponse status = ourClient.execute(httpGet); + try { + String responseContent = IOUtils.toString(status.getEntity().getContent()); + ourLog.info(status.getStatusLine().toString()); + ourLog.info(responseContent); + assertEquals(477, status.getStatusLine().getStatusCode()); + //assertEquals("SOME MESSAGE", status.getStatusLine().getReasonPhrase()); + assertThat(responseContent, stringContainsInOrder("business-rule")); + } finally { + IOUtils.closeQuietly(status.getEntity().getContent()); + } + + } + + @AfterClass + public static void afterClassClearContext() throws Exception { + ourServer.stop(); + TestUtil.clearAllStaticFieldsForUnitTest(); + } + + @BeforeClass + public static void beforeClass() throws Exception { + ourPort = PortUtil.findFreePort(); + ourServer = new Server(ourPort); + + DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider(); + + ServletHandler proxyHandler = new ServletHandler(); + RestfulServer servlet = new RestfulServer(ourCtx); + servlet.setPagingProvider(new FifoMemoryPagingProvider(10)); + + servlet.setResourceProviders(patientProvider); + ServletHolder servletHolder = new ServletHolder(servlet); + proxyHandler.addServletWithMapping(servletHolder, "/*"); + ourServer.setHandler(proxyHandler); + ourServer.start(); + + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS); + HttpClientBuilder builder = HttpClientBuilder.create(); + builder.setConnectionManager(connectionManager); + ourClient = builder.build(); + + } + + public static class DummyPatientResourceProvider implements IResourceProvider { + + @Override + public Class getResourceType() { + return Patient.class; + } + + @Search() + public List search() { + throw ourException; + } + + } + +} diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/SchemaValidationTestDstu3.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/SchemaValidationDstu3Test.java similarity index 86% rename from hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/SchemaValidationTestDstu3.java rename to hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/SchemaValidationDstu3Test.java index dbde0cb424f..f6ad6e7041d 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/SchemaValidationTestDstu3.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/SchemaValidationDstu3Test.java @@ -1,23 +1,20 @@ package ca.uhn.fhir.validation; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; -import java.util.Locale; - -import org.hl7.fhir.dstu3.model.Patient; import org.junit.AfterClass; import org.junit.Test; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.util.TestUtil; -public class SchemaValidationTestDstu3 { +public class SchemaValidationDstu3Test { private static FhirContext ourCtx = FhirContext.forDstu3(); - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SchemaValidationTestDstu3.class); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SchemaValidationDstu3Test.class); /** * See #339 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 26d87c5638a..f2613e46cdb 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -41,6 +41,16 @@ ]]> + + Remove some clases that were deprecated over a year ago and have + suitable replacements: + +
  • QualifiedDateParam has been removed, but DateParam may be used instead
  • +
  • PathSpecification has been removedm but Include may be used instead
  • + + ]]> +
    ResponseValidatingInterceptor threw an InternalErrorException (HTTP 500) for operations that do not return any content (e.g. delete). Thanks to Mohammad Jafari for reporting! @@ -359,6 +369,14 @@ Server now supports the _at parameter (including multiple repetitions) for history operation +