From 9b97fb0e9721262fe0251908b7d71cdd4c5fbe9a Mon Sep 17 00:00:00 2001
From: James Agnew
Date: Thu, 4 Jun 2015 10:56:13 -0400
Subject: [PATCH] Enable validation ($validate) operation in DSTU2 style
---
.../RestfulPatientResourceProviderMore.java | 5 +-
.../java/ca/uhn/fhir/android/BuiltJarIT.java | 10 +
.../uhn/fhir/parser/ErrorHandlerAdapter.java | 20 +
.../uhn/fhir/parser/IParserErrorHandler.java | 20 +
.../uhn/fhir/parser/LenientErrorHandler.java | 20 +
.../uhn/fhir/parser/StrictErrorHandler.java | 20 +
.../ca/uhn/fhir/rest/annotation/Validate.java | 27 +
.../uhn/fhir/rest/api/ValidationModeEnum.java | 28 +
.../uhn/fhir/rest/client/GenericClient.java | 7 +-
.../BaseAddOrDeleteTagsMethodBinding.java | 4 +-
.../fhir/rest/method/BaseMethodBinding.java | 59 +-
.../BaseOutcomeReturningMethodBinding.java | 15 +-
...turningMethodBindingWithResourceParam.java | 2 +-
.../BaseResourceReturningMethodBinding.java | 23 +-
.../rest/method/ConditionalParamBinder.java | 2 +-
.../rest/method/ConformanceMethodBinding.java | 2 +-
.../uhn/fhir/rest/method/CountParameter.java | 2 +-
.../fhir/rest/method/DeleteMethodBinding.java | 2 +-
.../method/DynamicSearchMethodBinding.java | 4 +-
.../rest/method/DynamicSearchParameter.java | 8 +-
.../rest/method/GetTagsMethodBinding.java | 6 +-
.../rest/method/HistoryMethodBinding.java | 2 +-
.../ca/uhn/fhir/rest/method/IParameter.java | 2 +-
.../ca/uhn/fhir/rest/method/MethodUtil.java | 36 +-
.../rest/method/NarrativeModeParameter.java | 2 +-
.../uhn/fhir/rest/method/NullParameter.java | 2 +-
.../rest/method/OperationMethodBinding.java | 35 +-
.../fhir/rest/method/OperationParameter.java | 85 +-
.../rest/method/OtherOperationTypeEnum.java | 19 +-
.../fhir/rest/method/ReadMethodBinding.java | 6 +-
.../java/ca/uhn/fhir/rest/method/Request.java | 158 ----
.../uhn/fhir/rest/method/RequestDetails.java | 119 +++
.../fhir/rest/method/SearchMethodBinding.java | 2 +-
.../rest/method/ServerBaseParamBinder.java | 2 +-
.../rest/method/ServletRequestParameter.java | 2 +-
.../rest/method/ServletResponseParameter.java | 2 +-
.../uhn/fhir/rest/method/SinceParameter.java | 2 +-
.../uhn/fhir/rest/method/SortParameter.java | 2 +-
.../rest/method/TransactionMethodBinding.java | 2 +-
.../fhir/rest/method/UpdateMethodBinding.java | 4 +-
...g.java => ValidateMethodBindingDstu1.java} | 6 +-
.../method/ValidateMethodBindingDstu2.java | 46 ++
.../fhir/rest/param/BaseQueryParameter.java | 3 +-
.../fhir/rest/param/ResourceParameter.java | 14 +-
.../fhir/rest/param/TransactionParameter.java | 4 +-
.../ca/uhn/fhir/rest/server/Constants.java | 10 +-
.../uhn/fhir/rest/server/ResourceBinding.java | 4 +-
.../uhn/fhir/rest/server/RestfulServer.java | 24 +-
.../fhir/rest/server/RestfulServerUtils.java | 519 ++++++------
.../fhir/rest/server/SearchParameterMap.java | 29 +-
.../ExceptionHandlingInterceptor.java | 3 +-
.../interceptor/LoggingInterceptor.java | 38 +-
.../instance/model/api/IBaseConformance.java | 20 +
.../fhir/instance/model/api/IBaseXhtml.java | 20 +
hapi-fhir-jpaserver-base/pom.xml | 13 +
.../provider/JpaResourceProviderDstu2.java | 95 ++-
.../provider/ResourceProviderDstu2Test.java | 738 ++++++++++--------
.../ca/uhn/fhirtest/TestRestfulServer.java | 2 +-
.../rp/FhirtestBaseResourceProviderDstu2.java | 8 +
.../WEB-INF/hapi-fhir-server-config.xml | 2 +-
.../ca/uhn/fhir/parser/XmlParserTest.java | 25 +
.../fhir/rest/server/ResourceMethodTest.java | 15 +-
...lidateTest.java => ValidateDstu1Test.java} | 4 +-
hapi-fhir-structures-dstu2/.gitignore | 1 +
.../fhir/rest/server/ValidateDstu2Test.java | 225 ++++++
.../interceptor/LoggingInterceptorTest.java | 148 +++-
hapi-fhir-structures-hl7org-dstu2/pom.xml | 21 +-
hapi-fhir-structures-hl7org-dstu2/tmp.txt | 1 +
pom.xml | 4 +-
src/changes/changes.xml | 3 +
src/site/xdoc/doc_rest_operations.xml | 25 +-
71 files changed, 1859 insertions(+), 981 deletions(-)
create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/ValidationModeEnum.java
delete mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/Request.java
rename hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/{ValidateMethodBinding.java => ValidateMethodBindingDstu1.java} (91%)
create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBindingDstu2.java
create mode 100644 hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/rp/FhirtestBaseResourceProviderDstu2.java
rename hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/{ValidateTest.java => ValidateDstu1Test.java} (98%)
create mode 100644 hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu2Test.java
rename {hapi-fhir-structures-dstu => hapi-fhir-structures-dstu2}/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorTest.java (60%)
create mode 100644 hapi-fhir-structures-hl7org-dstu2/tmp.txt
diff --git a/examples/src/main/java/example/RestfulPatientResourceProviderMore.java b/examples/src/main/java/example/RestfulPatientResourceProviderMore.java
index fb44a826950..662ca2691d6 100644
--- a/examples/src/main/java/example/RestfulPatientResourceProviderMore.java
+++ b/examples/src/main/java/example/RestfulPatientResourceProviderMore.java
@@ -59,6 +59,7 @@ import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
+import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
import ca.uhn.fhir.rest.param.CompositeParam;
@@ -836,7 +837,9 @@ public abstract MethodOutcome updateSomePatient(@IdParam IdDt theId, @ResourcePa
//START SNIPPET: validate
@Validate
-public MethodOutcome validatePatient(@ResourceParam Patient thePatient) {
+public MethodOutcome validatePatient(@ResourceParam Patient thePatient,
+ @Validate.Mode ValidationModeEnum theMode,
+ @Validate.Profile String theProfile) {
// Actually do our validation: The UnprocessableEntityException
// results in an HTTP 422, which is appropriate for business rule failure
diff --git a/hapi-fhir-android/src/test/java/ca/uhn/fhir/android/BuiltJarIT.java b/hapi-fhir-android/src/test/java/ca/uhn/fhir/android/BuiltJarIT.java
index f91a9578910..44724281a2f 100644
--- a/hapi-fhir-android/src/test/java/ca/uhn/fhir/android/BuiltJarIT.java
+++ b/hapi-fhir-android/src/test/java/ca/uhn/fhir/android/BuiltJarIT.java
@@ -66,6 +66,16 @@ public class BuiltJarIT {
}
for (File file : files) {
+ if (file.getName().endsWith("sources.jar")) {
+ continue;
+ }
+ if (file.getName().endsWith("javadoc.jar")) {
+ continue;
+ }
+ if (file.getName().contains("original.jar")) {
+ continue;
+ }
+
ourLog.info("Testing file: {}", file);
ZipFile zip = new ZipFile(file);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ErrorHandlerAdapter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ErrorHandlerAdapter.java
index e77119a69f9..e3a9ac00a7c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ErrorHandlerAdapter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ErrorHandlerAdapter.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.parser;
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2015 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%
+ */
+
/**
* Adapter implementation with NOP implementations of all {@link IParserErrorHandler} methods.
*/
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParserErrorHandler.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParserErrorHandler.java
index 7b53d450ded..2628c12cb6f 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParserErrorHandler.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParserErrorHandler.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.parser;
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2015 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%
+ */
+
/**
* Error handler
*/
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/LenientErrorHandler.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/LenientErrorHandler.java
index cd842ec2482..3eb1af8e6cb 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/LenientErrorHandler.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/LenientErrorHandler.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.parser;
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2015 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%
+ */
+
/**
* The default error handler, which logs issues but does not abort parsing
*
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/StrictErrorHandler.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/StrictErrorHandler.java
index 1522b13cdad..65b138a31c5 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/StrictErrorHandler.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/StrictErrorHandler.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.parser;
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2015 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%
+ */
+
/**
* Parser error handler which throws a {@link DataFormatException} any time an
* issue is found while parsing.
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/Validate.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/Validate.java
index 96404766f06..7b636616cba 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/Validate.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/Validate.java
@@ -26,6 +26,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import ca.uhn.fhir.model.api.IResource;
+import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.server.IResourceProvider;
/**
@@ -36,6 +37,12 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
* Validate is used to accept a resource, and test whether it would be acceptable for
* storing (e.g. using an update or create method)
*
+ *
+ * FHIR Version Note: The validate operation was defined as a type operation in DSTU1
+ * using a URL syntax like http://example.com/Patient/_validate
. In DSTU2, validation
+ * has been switched to being an extended operation using a URL syntax like
+ * http://example.com/Patient/$validate
, with a n
+ *
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value=ElementType.METHOD)
@@ -50,4 +57,24 @@ public @interface Validate {
// NB: Read, Search (maybe others) share this annotation, so update the javadocs everywhere
Class extends IResource> type() default IResource.class;
+ /**
+ * Validation mode parameter annotation for the validation mode parameter (only supported
+ * in FHIR DSTU2+). Parameter must be of type {@link ValidationModeEnum}.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(value=ElementType.PARAMETER)
+ @interface Mode {
+ // nothing
+ }
+
+ /**
+ * Validation mode parameter annotation for the validation URI parameter (only supported
+ * in FHIR DSTU2+). Parameter must be of type {@link String}.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(value=ElementType.PARAMETER)
+ @interface Profile {
+ // nothing
+ }
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/ValidationModeEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/ValidationModeEnum.java
new file mode 100644
index 00000000000..8f072c4829d
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/ValidationModeEnum.java
@@ -0,0 +1,28 @@
+package ca.uhn.fhir.rest.api;
+
+import org.hl7.fhir.instance.model.api.IBase;
+
+/**
+ * Validation mode parameter for the $validate operation (DSTU2+ only)
+ */
+public enum ValidationModeEnum implements IBase {
+ /**
+ * The server checks the content, and then checks that the content would be acceptable as a create (e.g. that the content would not validate any uniqueness constraints)
+ */
+ CREATE,
+
+ /**
+ * The server checks the content, and then checks that it would accept it as an update against the nominated specific resource (e.g. that there are no changes to immutable fields the server does not allow to change, and checking version integrity if appropriate)
+ */
+ UPDATE,
+
+ /**
+ * The server ignores the content, and checks that the nominated resource is allowed to be deleted (e.g. checking referential integrity rules)
+ */
+ DELETE;
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
index 51a975674cb..874d7f33987 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
@@ -20,7 +20,8 @@ package ca.uhn.fhir.rest.client;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.*;
+import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.io.Reader;
@@ -116,7 +117,7 @@ import ca.uhn.fhir.rest.method.ReadMethodBinding;
import ca.uhn.fhir.rest.method.SearchMethodBinding;
import ca.uhn.fhir.rest.method.SearchStyleEnum;
import ca.uhn.fhir.rest.method.TransactionMethodBinding;
-import ca.uhn.fhir.rest.method.ValidateMethodBinding;
+import ca.uhn.fhir.rest.method.ValidateMethodBindingDstu1;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
@@ -507,7 +508,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
@Override
public MethodOutcome validate(IResource theResource) {
- BaseHttpClientInvocation invocation = ValidateMethodBinding.createValidateInvocation(theResource, null, myContext);
+ BaseHttpClientInvocation invocation = ValidateMethodBindingDstu1.createValidateInvocation(theResource, null, myContext);
if (isKeepResponses()) {
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseAddOrDeleteTagsMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseAddOrDeleteTagsMethodBinding.java
index d7a18ba04f2..6a088473354 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseAddOrDeleteTagsMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseAddOrDeleteTagsMethodBinding.java
@@ -160,7 +160,7 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding
}
@Override
- public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
+ public void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
Object[] params = createParametersForServerRequest(theRequest, null);
params[myIdParamIndex] = theRequest.getId();
@@ -199,7 +199,7 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding
}
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (theRequest.getRequestType() != RequestTypeEnum.POST) {
return false;
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseMethodBinding.java
index bd0883659e4..34e78232bda 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseMethodBinding.java
@@ -38,6 +38,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
@@ -110,7 +111,7 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
return parser;
}
- protected IParser createAppropriateParserForParsingServerRequest(Request theRequest) {
+ protected IParser createAppropriateParserForParsingServerRequest(RequestDetails theRequest) {
String contentTypeHeader = theRequest.getServletRequest().getHeader("content-type");
EncodingEnum encoding;
if (isBlank(contentTypeHeader)) {
@@ -131,7 +132,7 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
return parser;
}
- protected Object[] createParametersForServerRequest(Request theRequest, byte[] theRequestContents) {
+ protected Object[] createParametersForServerRequest(RequestDetails theRequest, byte[] theRequestContents) {
Object[] params = new Object[getParameters().size()];
for (int i = 0; i < getParameters().size(); i++) {
IParameter param = getParameters().get(i);
@@ -241,11 +242,11 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
public abstract RestfulOperationSystemEnum getSystemOperationType();
- public abstract boolean incomingServerRequestMatchesMethod(Request theRequest);
+ public abstract boolean incomingServerRequestMatchesMethod(RequestDetails theRequest);
public abstract BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException;
- public abstract void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException;
+ public abstract void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException;
protected Object invokeServerMethod(Object[] theMethodParams) {
try {
@@ -262,7 +263,7 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
}
}
- protected byte[] loadRequestContents(Request theRequest) throws IOException {
+ protected byte[] loadRequestContents(RequestDetails theRequest) throws IOException {
byte[] requestContents = IOUtils.toByteArray(theRequest.getServletRequest().getInputStream());
return requestContents;
}
@@ -305,6 +306,30 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
myParameters = theParameters;
}
+ protected IBundleProvider toResourceList(Object response) throws InternalErrorException {
+ if (response == null) {
+ return BundleProviders.newEmptyList();
+ } else if (response instanceof IBundleProvider) {
+ return (IBundleProvider) response;
+ } else if (response instanceof IResource) {
+ return BundleProviders.newList((IResource) response);
+ } else if (response instanceof Collection) {
+ List retVal = new ArrayList();
+ for (Object next : ((Collection>) response)) {
+ retVal.add((IBaseResource) next);
+ }
+ return BundleProviders.newList(retVal);
+ } else if (response instanceof MethodOutcome) {
+ IBaseResource retVal = ((MethodOutcome) response).getOperationOutcome();
+ if (retVal == null) {
+ retVal = getContext().getResourceDefinition("OperationOutcome").newInstance();
+ }
+ return BundleProviders.newList(retVal);
+ } else {
+ throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
+ }
+ }
+
@SuppressWarnings("unchecked")
public static BaseMethodBinding> bindMethod(Method theMethod, FhirContext theContext, Object theProvider) {
Read read = theMethod.getAnnotation(Read.class);
@@ -438,7 +463,11 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
} else if (history != null) {
return new HistoryMethodBinding(theMethod, theContext, theProvider);
} else if (validate != null) {
- return new ValidateMethodBinding(theMethod, theContext, theProvider);
+ if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
+ return new ValidateMethodBindingDstu1(theMethod, theContext, theProvider);
+ } else {
+ return new ValidateMethodBindingDstu2(returnType, returnTypeFromRp, theMethod, theContext, theProvider, validate);
+ }
} else if (getTags != null) {
return new GetTagsMethodBinding(theMethod, theContext, theProvider, getTags);
} else if (addTags != null) {
@@ -491,24 +520,6 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
return theType.getCanonicalName();
}
- protected static IBundleProvider toResourceList(Object response) throws InternalErrorException {
- if (response == null) {
- return BundleProviders.newEmptyList();
- } else if (response instanceof IBundleProvider) {
- return (IBundleProvider) response;
- } else if (response instanceof IResource) {
- return BundleProviders.newList((IResource) response);
- } else if (response instanceof Collection) {
- List retVal = new ArrayList();
- for (Object next : ((Collection>) response)) {
- retVal.add((IBaseResource) next);
- }
- return BundleProviders.newList(retVal);
- } else {
- throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
- }
- }
-
private static boolean verifyIsValidResourceReturnType(Class> theReturnType) {
if (theReturnType == null) {
return false;
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 9e5f2b4f65b..6886d35084b 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
@@ -67,7 +67,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding allowableRequestTypes = provideAllowableRequestTypes();
RequestTypeEnum requestType = theRequest.getRequestType();
if (!allowableRequestTypes.contains(requestType)) {
@@ -120,8 +120,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding> theHeaders) throws IOException,
- BaseServerResponseException {
+ public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws BaseServerResponseException {
switch (theResponseStatusCode) {
case Constants.STATUS_HTTP_200_OK:
case Constants.STATUS_HTTP_201_CREATED:
@@ -138,7 +137,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding provideAllowableRequestTypes();
- protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, Request theRequest)
+ protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, RequestDetails theRequest)
throws IOException {
theResponse.setStatus(theE.getStatusCode());
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBindingWithResourceParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBindingWithResourceParam.java
index ef885208efc..55245dd579d 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBindingWithResourceParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBindingWithResourceParam.java
@@ -80,7 +80,7 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
}
@Override
- protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
+ protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
if (myIdParamIndex != null) {
theParams[myIdParamIndex] = theRequest.getId();
}
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 b234de7b7a7..5c5513f2cd8 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
@@ -20,7 +20,7 @@ package ca.uhn.fhir.rest.method;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.*;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.io.Reader;
@@ -45,8 +45,10 @@ import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
import ca.uhn.fhir.rest.server.Constants;
@@ -112,6 +114,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding> theHeaders) throws IOException {
+ public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) {
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theResponseStatusCode);
switch (getReturnType()) {
@@ -191,6 +195,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
if (myOperationType == RestfulOperationTypeEnum.CREATE) {
String retVal = theRequest.getServletRequest().getHeader(Constants.HEADER_IF_NONE_EXIST);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ConformanceMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ConformanceMethodBinding.java
index 643abdf5985..e0756f1f535 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ConformanceMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ConformanceMethodBinding.java
@@ -75,7 +75,7 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
}
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (theRequest.getRequestType() == RequestTypeEnum.OPTIONS) {
return true;
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/CountParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/CountParameter.java
index c3479dd3977..87003347a4e 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/CountParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/CountParameter.java
@@ -54,7 +54,7 @@ public class CountParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
String[] sinceParams = theRequest.getParameters().remove(Constants.PARAM_COUNT);
if (sinceParams != null) {
if (sinceParams.length > 0) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DeleteMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DeleteMethodBinding.java
index 51c04c95942..566c1613687 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DeleteMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DeleteMethodBinding.java
@@ -143,7 +143,7 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
}
@Override
- protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
+ protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
theParams[myIdParameterIndex] = theRequest.getId();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DynamicSearchMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DynamicSearchMethodBinding.java
index 72070fbbbcc..99e00231182 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DynamicSearchMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DynamicSearchMethodBinding.java
@@ -74,7 +74,7 @@ public class DynamicSearchMethodBinding extends BaseResourceReturningMethodBindi
List retVal = new ArrayList(super.getParameters());
for (RuntimeSearchParam next : mySearchParameters) {
-
+ // TODO: what is this?
}
return retVal;
@@ -108,7 +108,7 @@ public class DynamicSearchMethodBinding extends BaseResourceReturningMethodBindi
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DynamicSearchMethodBinding.class);
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (!theRequest.getResourceName().equals(getResourceName())) {
ourLog.trace("Method {} doesn't match because resource name {} != {}", getMethod().getName(), theRequest.getResourceName(), getResourceName());
return false;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DynamicSearchParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DynamicSearchParameter.java
index b6bce57264f..bafd18ff861 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DynamicSearchParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DynamicSearchParameter.java
@@ -44,6 +44,7 @@ import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.param.TokenParam;
+import ca.uhn.fhir.rest.param.UriOrListParam;
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider;
import ca.uhn.fhir.rest.server.SearchParameterMap;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
@@ -66,7 +67,7 @@ public class DynamicSearchParameter implements IParameter {
@SuppressWarnings("unchecked")
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
SearchParameterMap retVal = new SearchParameterMap();
for (String next : theRequest.getParameters().keySet()) {
@@ -133,6 +134,11 @@ public class DynamicSearchParameter implements IParameter {
tokenOrListParam.setValuesAsQueryTokens(paramList);
retVal.add(next, tokenOrListParam);
break;
+ case URI:
+ UriOrListParam uriOrListParam = new UriOrListParam();
+ uriOrListParam.setValuesAsQueryTokens(paramList);
+ retVal.add(next, uriOrListParam);
+ break;
}
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/GetTagsMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/GetTagsMethodBinding.java
index d3539e5e008..5abe5bcf24c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/GetTagsMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/GetTagsMethodBinding.java
@@ -82,7 +82,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding {
}
@Override
- public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException, BaseServerResponseException {
+ public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws BaseServerResponseException {
if (theResponseStatusCode == Constants.STATUS_HTTP_200_OK) {
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theResponseStatusCode);
TagList retVal = parser.parseTagList(theResponseReader);
@@ -148,7 +148,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding {
}
@Override
- public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
+ public void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
Object[] params = createParametersForServerRequest(theRequest, null);
if (myIdParamIndex != null) {
@@ -188,7 +188,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding {
}
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (theRequest.getRequestType()!=RequestTypeEnum.GET) {
return false;
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java
index fdcf9157587..f83e47b6858 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java
@@ -114,7 +114,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
// ObjectUtils.equals is replaced by a JDK7 method..
@SuppressWarnings("deprecation")
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (!Constants.PARAM_HISTORY.equals(theRequest.getOperation())) {
return false;
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/IParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/IParameter.java
index c84c3fc3f43..51bd0febf5d 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/IParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/IParameter.java
@@ -48,7 +48,7 @@ public interface IParameter {
* @param theMethodBinding TODO
* @return Returns the argument object as it will be passed to the {@link IResourceProvider} method.
*/
- Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException;
+ Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException;
void initializeTypes(Method theMethod, Class extends Collection>> theOuterCollectionType, Class extends Collection>> theInnerCollectionType, Class> theParameterType);
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 c32af007c00..88f66f3bd6b 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
@@ -48,6 +48,7 @@ import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
+import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
import ca.uhn.fhir.rest.annotation.Count;
@@ -64,9 +65,12 @@ import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.annotation.Sort;
import ca.uhn.fhir.rest.annotation.TagListParam;
import ca.uhn.fhir.rest.annotation.TransactionParam;
+import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.annotation.VersionIdParam;
import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
+import ca.uhn.fhir.rest.method.OperationParameter.IConverter;
import ca.uhn.fhir.rest.param.CollectionBinder;
import ca.uhn.fhir.rest.param.DateAndListParam;
import ca.uhn.fhir.rest.param.NumberAndListParam;
@@ -436,7 +440,37 @@ public class MethodUtil {
param = new ConditionalParamBinder(theRestfulOperationTypeEnum);
} else if (nextAnnotation instanceof OperationParam) {
Operation op = theMethod.getAnnotation(Operation.class);
- param = new OperationParameter(op.name(), (OperationParam) nextAnnotation);
+ param = new OperationParameter(op.name(), ((OperationParam) nextAnnotation).name());
+ } else if (nextAnnotation instanceof Validate.Mode) {
+ if (parameterType.equals(ValidationModeEnum.class) == false) {
+ throw new ConfigurationException("Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Mode.class.getSimpleName() + " must be of type " + ValidationModeEnum.class.getName());
+ }
+ param = new OperationParameter(Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_MODE).setConverter(new IConverter() {
+ @Override
+ public Object outgoingClient(Object theObject) {
+ return new StringDt(((ValidationModeEnum)theObject).name().toLowerCase());
+ }
+
+ @Override
+ public Object incomingServer(Object theObject) {
+ return ValidationModeEnum.valueOf(theObject.toString().toUpperCase());
+ }
+ });
+ } else if (nextAnnotation instanceof Validate.Profile) {
+ if (parameterType.equals(String.class) == false) {
+ throw new ConfigurationException("Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Profile.class.getSimpleName() + " must be of type " + String.class.getName());
+ }
+ param = new OperationParameter(Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_PROFILE).setConverter(new IConverter() {
+ @Override
+ public Object outgoingClient(Object theObject) {
+ return new StringDt(theObject.toString());
+ }
+
+ @Override
+ public Object incomingServer(Object theObject) {
+ return theObject.toString();
+ }
+ });
} else {
continue;
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/NarrativeModeParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/NarrativeModeParameter.java
index 2a4e24fb08e..3d3c11fe380 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/NarrativeModeParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/NarrativeModeParameter.java
@@ -47,7 +47,7 @@ class NarrativeModeParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
String val = theRequest.getServletRequest().getParameter(Constants.PARAM_NARRATIVE);
if (val != null) {
try {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/NullParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/NullParameter.java
index 0f81f69cef8..428bbd27f62 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/NullParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/NullParameter.java
@@ -39,7 +39,7 @@ class NullParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
// nothing
return null;
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationMethodBinding.java
index 4b927183dc0..d1bcd732de9 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationMethodBinding.java
@@ -59,23 +59,28 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
private final Integer myIdParamIndex;
private final String myName;
private final ReturnTypeEnum myReturnType;
+ private final OtherOperationTypeEnum myOtherOperatiopnType;
public OperationMethodBinding(Class> theReturnResourceType, Class extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
Operation theAnnotation) {
+ this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.name(), theAnnotation.type());
+ }
+
+ public OperationMethodBinding(Class> theReturnResourceType, Class extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider, boolean theIdempotent, String theOperationName,
+ Class extends IBaseResource> theOperationType) {
super(theReturnResourceType, theMethod, theContext, theProvider);
- myHttpGetPermitted = theAnnotation.idempotent();
+ myHttpGetPermitted = theIdempotent;
myIdParamIndex = MethodUtil.findIdParameterIndex(theMethod);
- String name = theAnnotation.name();
- if (isBlank(name)) {
+ if (isBlank(theOperationName)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getName() + " is annotated with @" + Operation.class.getSimpleName()
+ " but this annotation has no name defined");
}
- if (name.startsWith("$") == false) {
- name = "$" + name;
+ if (theOperationName.startsWith("$") == false) {
+ theOperationName = "$" + theOperationName;
}
- myName = name;
+ myName = theOperationName;
if (theContext.getVersion().getVersion().isEquivalentTo(FhirVersionEnum.DSTU1)) {
throw new ConfigurationException("@" + Operation.class.getSimpleName() + " methods are not supported on servers for FHIR version " + theContext.getVersion().getVersion().name());
@@ -84,8 +89,8 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
if (theReturnTypeFromRp != null) {
setResourceName(theContext.getResourceDefinition(theReturnTypeFromRp).getName());
} else {
- if (Modifier.isAbstract(theAnnotation.type().getModifiers()) == false) {
- setResourceName(theContext.getResourceDefinition(theAnnotation.type()).getName());
+ if (Modifier.isAbstract(theOperationType.getModifiers()) == false) {
+ setResourceName(theContext.getResourceDefinition(theOperationType).getName());
} else {
setResourceName(null);
}
@@ -102,6 +107,18 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
myReturnType = ReturnTypeEnum.RESOURCE;
}
+ if (getResourceName() == null) {
+ myOtherOperatiopnType = OtherOperationTypeEnum.EXTENDED_OPERATION_SERVER;
+ } else if (myIdParamIndex == null) {
+ myOtherOperatiopnType = OtherOperationTypeEnum.EXTENDED_OPERATION_TYPE;
+ } else {
+ myOtherOperatiopnType = OtherOperationTypeEnum.EXTENDED_OPERATION_INSTANCE;
+ }
+ }
+
+ @Override
+ public OtherOperationTypeEnum getOtherOperationType() {
+ return myOtherOperatiopnType;
}
@Override
@@ -125,7 +142,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
}
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (getResourceName() == null) {
if (isNotBlank(theRequest.getResourceName())) {
return false;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationParameter.java
index 3242b3ea7d7..e5b96b776d3 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationParameter.java
@@ -41,43 +41,25 @@ import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.i18n.HapiLocalizer;
import ca.uhn.fhir.model.primitive.StringDt;
-import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.param.CollectionBinder;
import ca.uhn.fhir.rest.param.ResourceParameter;
-import ca.uhn.fhir.rest.server.EncodingEnum;
-import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
class OperationParameter implements IParameter {
- private final String myName;
- private Class> myParameterType;
+ private IConverter myConverter;
@SuppressWarnings("rawtypes")
private Class extends Collection> myInnerCollectionType;
+ private final String myName;
private final String myOperationName;
+ private Class> myParameterType;
- OperationParameter(String theOperationName, OperationParam theAnnotation) {
+ OperationParameter(String theOperationName, String theParameterName) {
myOperationName = theOperationName;
- myName = theAnnotation.name();
- }
-
- @Override
- public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map> theTargetQueryArguments, IBaseResource theTargetResource)
- throws InternalErrorException {
- assert theTargetResource != null;
- if (theSourceClientArgument == null) {
- return;
- }
-
- RuntimeResourceDefinition def = theContext.getResourceDefinition(theTargetResource);
-
- BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
- BaseRuntimeElementCompositeDefinition> paramChildElem = (BaseRuntimeElementCompositeDefinition>) paramChild.getChildByName("parameter");
-
- addClientParameter(theContext, theSourceClientArgument, theTargetResource, paramChild, paramChildElem);
+ myName = theParameterName;
}
private void addClientParameter(FhirContext theContext, Object theSourceClientArgument, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition> paramChildElem) {
@@ -96,7 +78,7 @@ class OperationParameter implements IParameter {
throw new IllegalArgumentException("Don't know how to handle value of type " + theSourceClientArgument.getClass() + " for paramater " + myName);
}
}
-
+
private IBase createParameterRepetition(FhirContext theContext, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition> paramChildElem) {
IBase parameter = paramChildElem.newInstance();
paramChild.getMutator().addValue(theTargetResource, parameter);
@@ -110,9 +92,43 @@ class OperationParameter implements IParameter {
return parameter;
}
+ @Override
+ public void initializeTypes(Method theMethod, Class extends Collection>> theOuterCollectionType, Class extends Collection>> theInnerCollectionType, Class> theParameterType) {
+ myParameterType = theParameterType;
+ if (theInnerCollectionType != null) {
+ myInnerCollectionType = CollectionBinder.getInstantiableCollectionType(theInnerCollectionType, myName);
+ }
+ }
+
+ public OperationParameter setConverter(IConverter theConverter) {
+ myConverter = theConverter;
+ return this;
+ }
+
+ @Override
+ public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map> theTargetQueryArguments, IBaseResource theTargetResource)
+ throws InternalErrorException {
+ assert theTargetResource != null;
+ Object sourceClientArgument = theSourceClientArgument;
+ if (sourceClientArgument == null) {
+ return;
+ }
+
+ if (myConverter != null) {
+ sourceClientArgument = myConverter.outgoingClient(sourceClientArgument);
+ }
+
+ RuntimeResourceDefinition def = theContext.getResourceDefinition(theTargetResource);
+
+ BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
+ BaseRuntimeElementCompositeDefinition> paramChildElem = (BaseRuntimeElementCompositeDefinition>) paramChild.getChildByName("parameter");
+
+ addClientParameter(theContext, sourceClientArgument, theTargetResource, paramChild, paramChildElem);
+ }
+
@SuppressWarnings("unchecked")
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
List matchingParamValues = new ArrayList();
if (theRequest.getRequestType() == RequestTypeEnum.GET) {
@@ -199,10 +215,13 @@ class OperationParameter implements IParameter {
}
private void tryToAddValues(List theParamValues, List theMatchingParamValues) {
- for (IBase nextValue : theParamValues) {
+ for (Object nextValue : theParamValues) {
if (nextValue == null) {
continue;
}
+ if (myConverter != null) {
+ nextValue = myConverter.incomingServer(nextValue);
+ }
if (!myParameterType.isAssignableFrom(nextValue.getClass())) {
throw new InvalidRequestException("Request has parameter " + myName + " of type " + nextValue.getClass().getSimpleName() + " but method expects type "
+ myParameterType.getSimpleName());
@@ -211,12 +230,12 @@ class OperationParameter implements IParameter {
}
}
- @Override
- public void initializeTypes(Method theMethod, Class extends Collection>> theOuterCollectionType, Class extends Collection>> theInnerCollectionType, Class> theParameterType) {
- myParameterType = theParameterType;
- if (theInnerCollectionType != null) {
- myInnerCollectionType = CollectionBinder.getInstantiableCollectionType(theInnerCollectionType, myName);
- }
- }
+ public interface IConverter {
+
+ Object incomingServer(Object theObject);
+ Object outgoingClient(Object theObject);
+
+ }
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OtherOperationTypeEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OtherOperationTypeEnum.java
index f5baf0c2c20..972a66b5fc9 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OtherOperationTypeEnum.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OtherOperationTypeEnum.java
@@ -30,8 +30,23 @@ public enum OtherOperationTypeEnum {
GET_TAGS("get-tags"),
- GET_PAGE("get-page");
-
+ GET_PAGE("get-page"),
+
+ /**
+ * E.g. $everything, $validate, etc.
+ */
+ EXTENDED_OPERATION_SERVER("extended-operation-server"),
+
+ /**
+ * E.g. $everything, $validate, etc.
+ */
+ EXTENDED_OPERATION_TYPE("extended-operation-type"),
+
+ /**
+ * E.g. $everything, $validate, etc.
+ */
+ EXTENDED_OPERATION_INSTANCE("extended-operation-instance");
+
private String myCode;
OtherOperationTypeEnum(String theName) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ReadMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ReadMethodBinding.java
index d0689224baf..986b6070703 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ReadMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ReadMethodBinding.java
@@ -110,7 +110,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
}
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (!theRequest.getResourceName().equals(getResourceName())) {
return false;
}
@@ -186,7 +186,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
case RESOURCE:
return resource;
case BUNDLE_PROVIDER:
- return new SimpleBundleProvider((IResource) resource);
+ return new SimpleBundleProvider(resource);
}
throw new IllegalStateException("" + getMethodReturnType()); // should not happen
@@ -203,7 +203,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
IBundleProvider retVal = toResourceList(response);
if (theRequest.getServer().getETagSupport() == ETagSupportEnum.ENABLED) {
- String ifNoneMatch = ((Request)theRequest).getServletRequest().getHeader(Constants.HEADER_IF_NONE_MATCH_LC);
+ String ifNoneMatch = theRequest.getServletRequest().getHeader(Constants.HEADER_IF_NONE_MATCH_LC);
if (retVal.size() == 1 && StringUtils.isNotBlank(ifNoneMatch)) {
List responseResources = retVal.getResources(0, 1);
IBaseResource responseResource = responseResources.get(0);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/Request.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/Request.java
deleted file mode 100644
index af97871b49c..00000000000
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/Request.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package ca.uhn.fhir.rest.method;
-
-/*
- * #%L
- * HAPI FHIR - Core Library
- * %%
- * Copyright (C) 2014 - 2015 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.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import ca.uhn.fhir.rest.api.RequestTypeEnum;
-
-/**
- * This class is internal to HAPI - Use with caution as methods may change in future versions of the library
- */
-public class Request extends RequestDetails {
-
- private String myFhirServerBase;
- private String myOperation;
- private String myRequestPath;
- private boolean myRespondGzip;
- private String mySecondaryOperation;
- private HttpServletRequest myServletRequest;
- private HttpServletResponse myServletResponse;
- private Map> myUnqualifiedToQualifiedNames;
-
- public String getFhirServerBase() {
- return myFhirServerBase;
- }
-
- public String getOperation() {
- return myOperation;
- }
-
-
- /**
- * The part of the request URL that comes after the server base.
- *
- * Will not contain a leading '/'
- *
- */
- public String getRequestPath() {
- return myRequestPath;
- }
-
- public String getSecondaryOperation() {
- return mySecondaryOperation;
- }
-
- public HttpServletRequest getServletRequest() {
- return myServletRequest;
- }
-
- public HttpServletResponse getServletResponse() {
- return myServletResponse;
- }
-
- public Map> getUnqualifiedToQualifiedNames() {
- return myUnqualifiedToQualifiedNames;
- }
-
- public boolean isRespondGzip() {
- return myRespondGzip;
- }
-
- public void setFhirServerBase(String theFhirServerBase) {
- myFhirServerBase = theFhirServerBase;
- }
-
- public void setOperation(String theOperation) {
- myOperation = theOperation;
- }
-
- @Override
- public void setParameters(Map theParams) {
- super.setParameters(theParams);
-
- for (String next : theParams.keySet()) {
- for (int i = 0; i < next.length(); i++) {
- char nextChar = next.charAt(i);
- if (nextChar == ':' || nextChar == '.') {
- if (myUnqualifiedToQualifiedNames == null) {
- myUnqualifiedToQualifiedNames = new HashMap>();
- }
- String unqualified = next.substring(0, i);
- List list = myUnqualifiedToQualifiedNames.get(unqualified);
- if (list == null) {
- list = new ArrayList(4);
- myUnqualifiedToQualifiedNames.put(unqualified, list);
- }
- list.add(next);
- break;
- }
- }
- }
-
- if (myUnqualifiedToQualifiedNames == null) {
- myUnqualifiedToQualifiedNames = Collections.emptyMap();
- }
-
- }
-
- public void setRequestPath(String theRequestPath) {
- assert theRequestPath.length() == 0 || theRequestPath.charAt(0) != '/';
- myRequestPath = theRequestPath;
- }
-
- public void setRespondGzip(boolean theRespondGzip) {
- myRespondGzip = theRespondGzip;
- }
-
- public void setSecondaryOperation(String theSecondaryOperation) {
- mySecondaryOperation = theSecondaryOperation;
- }
-
- public void setServletRequest(HttpServletRequest theRequest) {
- myServletRequest = theRequest;
- }
-
- public void setServletResponse(HttpServletResponse theServletResponse) {
- myServletResponse = theServletResponse;
- }
-
- public static Request withResourceAndParams(String theResourceName, RequestTypeEnum theRequestType, Set theParamNames) {
- Request retVal = new Request();
- retVal.setResourceName(theResourceName);
- retVal.setRequestType(theRequestType);
- Map paramNames = new HashMap();
- for (String next : theParamNames) {
- paramNames.put(next, new String[0]);
- }
- retVal.setParameters(paramNames);
- return retVal;
- }
-
-}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/RequestDetails.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/RequestDetails.java
index 9201f80cf09..dcfcbbbd7b0 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/RequestDetails.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/RequestDetails.java
@@ -20,7 +20,15 @@ package ca.uhn.fhir.rest.method;
* #L%
*/
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
@@ -32,14 +40,22 @@ public class RequestDetails {
private String myCompartmentName;
private String myCompleteUrl;
+ private String myFhirServerBase;
private IdDt myId;
+ private String myOperation;
private OtherOperationTypeEnum myOtherOperationType;
private Map myParameters;
+ private String myRequestPath;
private RequestTypeEnum myRequestType;
private String myResourceName;
private RestfulOperationTypeEnum myResourceOperationType;
+ private boolean myRespondGzip;
+ private String mySecondaryOperation;
private RestfulServer myServer;
+ private HttpServletRequest myServletRequest;
+ private HttpServletResponse myServletResponse;
private RestfulOperationSystemEnum mySystemOperationType;
+ private Map> myUnqualifiedToQualifiedNames;
public String getCompartmentName() {
return myCompartmentName;
@@ -49,10 +65,18 @@ public class RequestDetails {
return myCompleteUrl;
}
+ public String getFhirServerBase() {
+ return myFhirServerBase;
+ }
+
public IdDt getId() {
return myId;
}
+ public String getOperation() {
+ return myOperation;
+ }
+
public OtherOperationTypeEnum getOtherOperationType() {
return myOtherOperationType;
}
@@ -61,6 +85,16 @@ public class RequestDetails {
return myParameters;
}
+ /**
+ * The part of the request URL that comes after the server base.
+ *
+ * Will not contain a leading '/'
+ *
+ */
+ public String getRequestPath() {
+ return myRequestPath;
+ }
+
public RequestTypeEnum getRequestType() {
return myRequestType;
}
@@ -73,14 +107,34 @@ public class RequestDetails {
return myResourceOperationType;
}
+ public String getSecondaryOperation() {
+ return mySecondaryOperation;
+ }
+
public RestfulServer getServer() {
return myServer;
}
+ public HttpServletRequest getServletRequest() {
+ return myServletRequest;
+ }
+
+ public HttpServletResponse getServletResponse() {
+ return myServletResponse;
+ }
+
public RestfulOperationSystemEnum getSystemOperationType() {
return mySystemOperationType;
}
+ public Map> getUnqualifiedToQualifiedNames() {
+ return myUnqualifiedToQualifiedNames;
+ }
+
+ public boolean isRespondGzip() {
+ return myRespondGzip;
+ }
+
public void setCompartmentName(String theCompartmentName) {
myCompartmentName = theCompartmentName;
}
@@ -89,16 +143,53 @@ public class RequestDetails {
myCompleteUrl = theCompleteUrl;
}
+ public void setFhirServerBase(String theFhirServerBase) {
+ myFhirServerBase = theFhirServerBase;
+ }
+
public void setId(IdDt theId) {
myId = theId;
}
+ public void setOperation(String theOperation) {
+ myOperation = theOperation;
+ }
+
public void setOtherOperationType(OtherOperationTypeEnum theOtherOperationType) {
myOtherOperationType = theOtherOperationType;
}
public void setParameters(Map theParams) {
myParameters = theParams;
+
+ for (String next : theParams.keySet()) {
+ for (int i = 0; i < next.length(); i++) {
+ char nextChar = next.charAt(i);
+ if (nextChar == ':' || nextChar == '.') {
+ if (myUnqualifiedToQualifiedNames == null) {
+ myUnqualifiedToQualifiedNames = new HashMap>();
+ }
+ String unqualified = next.substring(0, i);
+ List list = myUnqualifiedToQualifiedNames.get(unqualified);
+ if (list == null) {
+ list = new ArrayList(4);
+ myUnqualifiedToQualifiedNames.put(unqualified, list);
+ }
+ list.add(next);
+ break;
+ }
+ }
+ }
+
+ if (myUnqualifiedToQualifiedNames == null) {
+ myUnqualifiedToQualifiedNames = Collections.emptyMap();
+ }
+
+ }
+
+ public void setRequestPath(String theRequestPath) {
+ assert theRequestPath.length() == 0 || theRequestPath.charAt(0) != '/';
+ myRequestPath = theRequestPath;
}
public void setRequestType(RequestTypeEnum theRequestType) {
@@ -113,12 +204,40 @@ public class RequestDetails {
myResourceOperationType = theResourceOperationType;
}
+ public void setRespondGzip(boolean theRespondGzip) {
+ myRespondGzip = theRespondGzip;
+ }
+
+ public void setSecondaryOperation(String theSecondaryOperation) {
+ mySecondaryOperation = theSecondaryOperation;
+ }
+
public void setServer(RestfulServer theServer) {
myServer = theServer;
}
+ public void setServletRequest(HttpServletRequest theRequest) {
+ myServletRequest = theRequest;
+ }
+
+ public void setServletResponse(HttpServletResponse theServletResponse) {
+ myServletResponse = theServletResponse;
+ }
+
public void setSystemOperationType(RestfulOperationSystemEnum theSystemOperationType) {
mySystemOperationType = theSystemOperationType;
}
+ public static RequestDetails withResourceAndParams(String theResourceName, RequestTypeEnum theRequestType, Set theParamNames) {
+ RequestDetails retVal = new RequestDetails();
+ retVal.setResourceName(theResourceName);
+ retVal.setRequestType(theRequestType);
+ Map paramNames = new HashMap();
+ for (String next : theParamNames) {
+ paramNames.put(next, new String[0]);
+ }
+ retVal.setParameters(paramNames);
+ return retVal;
+ }
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SearchMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SearchMethodBinding.java
index 82a8dd6701b..072224592d6 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SearchMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SearchMethodBinding.java
@@ -148,7 +148,7 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
}
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (!theRequest.getResourceName().equals(getResourceName())) {
ourLog.trace("Method {} doesn't match because resource name {} != {}", getMethod().getName(), theRequest.getResourceName(), getResourceName());
return false;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServerBaseParamBinder.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServerBaseParamBinder.java
index bc471fc6e88..8e7f44af757 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServerBaseParamBinder.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServerBaseParamBinder.java
@@ -43,7 +43,7 @@ class ServerBaseParamBinder implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
return theRequest.getFhirServerBase();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletRequestParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletRequestParameter.java
index 263369ec09a..31b132a9340 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletRequestParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletRequestParameter.java
@@ -43,7 +43,7 @@ class ServletRequestParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
return theRequest.getServletRequest();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletResponseParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletResponseParameter.java
index 5e363d34549..89e571e8b1b 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletResponseParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletResponseParameter.java
@@ -43,7 +43,7 @@ class ServletResponseParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
return theRequest.getServletResponse();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SinceParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SinceParameter.java
index 64001c95747..5e3a3f90a0d 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SinceParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SinceParameter.java
@@ -54,7 +54,7 @@ class SinceParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
String[] sinceParams = theRequest.getParameters().remove(Constants.PARAM_SINCE);
if (sinceParams != null) {
if (sinceParams.length > 0) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SortParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SortParameter.java
index f0c33c02392..27b21ee28a5 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SortParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/SortParameter.java
@@ -65,7 +65,7 @@ public class SortParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT)) {
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_ASC)) {
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_DESC)) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionMethodBinding.java
index 796005dac92..b4262a54631 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionMethodBinding.java
@@ -97,7 +97,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
}
@Override
- public boolean incomingServerRequestMatchesMethod(Request theRequest) {
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (theRequest.getRequestType() != RequestTypeEnum.POST) {
return false;
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java
index fe3f0c1036e..4c5fb18f507 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java
@@ -59,7 +59,7 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
}
@Override
- protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
+ protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
/*
* We are being a bit lenient here, since technically the client is supposed to include the version in the
* Content-Location header, but we allow it in the PUT URL as well..
@@ -122,7 +122,7 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
}
/*
- * @Override public boolean incomingServerRequestMatchesMethod(Request theRequest) { if
+ * @Override public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) { if
* (super.incomingServerRequestMatchesMethod(theRequest)) { if (myVersionIdParameterIndex != null) { if
* (theRequest.getVersionId() == null) { return false; } } else { if (theRequest.getVersionId() != null) { return
* false; } } return true; } else { return false; } }
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBindingDstu1.java
similarity index 91%
rename from hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBinding.java
rename to hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBindingDstu1.java
index 487495b6324..282a64702bc 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBindingDstu1.java
@@ -34,11 +34,11 @@ import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.server.Constants;
-public class ValidateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
+public class ValidateMethodBindingDstu1 extends BaseOutcomeReturningMethodBindingWithResourceParam {
private Integer myIdParameterIndex;
- public ValidateMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
+ public ValidateMethodBindingDstu1(Method theMethod, FhirContext theContext, Object theProvider) {
super(theMethod, theContext, Validate.class, theProvider);
myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod);
@@ -55,7 +55,7 @@ public class ValidateMethodBinding extends BaseOutcomeReturningMethodBindingWith
}
@Override
- protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
+ protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
if (myIdParameterIndex != null) {
theParams[myIdParameterIndex] = theRequest.getId();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBindingDstu2.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBindingDstu2.java
new file mode 100644
index 00000000000..d44cc7507cf
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ValidateMethodBindingDstu2.java
@@ -0,0 +1,46 @@
+package ca.uhn.fhir.rest.method;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.rest.annotation.Validate;
+import ca.uhn.fhir.rest.param.ResourceParameter;
+import ca.uhn.fhir.rest.server.Constants;
+import ca.uhn.fhir.rest.server.EncodingEnum;
+
+public class ValidateMethodBindingDstu2 extends OperationMethodBinding {
+
+ public ValidateMethodBindingDstu2(Class> theReturnResourceType, Class extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
+ Validate theAnnotation) {
+ super(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type());
+
+ List newParams = new ArrayList();
+ int idx = 0;
+ for (IParameter next : getParameters()) {
+ if (next instanceof ResourceParameter) {
+ if (IBaseResource.class.isAssignableFrom(((ResourceParameter) next).getResourceType())) {
+ Class> parameterType = theMethod.getParameterTypes()[idx];
+ if (String.class.equals(parameterType) || EncodingEnum.class.equals(parameterType)) {
+ newParams.add(next);
+ } else {
+ OperationParameter parameter = new OperationParameter(Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_RESOURCE);
+ parameter.initializeTypes(theMethod, null, null, parameterType);
+ newParams.add(parameter);
+ }
+ } else {
+ newParams.add(next);
+ }
+ } else {
+ newParams.add(next);
+ }
+ idx++;
+ }
+ setParameters(newParams);
+
+ }
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseQueryParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseQueryParameter.java
index b1cdeac2b63..49b72fb358f 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseQueryParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseQueryParameter.java
@@ -34,7 +34,6 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.method.IParameter;
import ca.uhn.fhir.rest.method.QualifiedParamList;
-import ca.uhn.fhir.rest.method.Request;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.method.SearchMethodBinding;
@@ -130,7 +129,7 @@ public abstract class BaseQueryParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
List paramList = new ArrayList();
String name = getName();
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ResourceParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ResourceParameter.java
index 6d49477c35b..3e53466d65c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ResourceParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ResourceParameter.java
@@ -20,7 +20,8 @@ package ca.uhn.fhir.rest.param;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.*;
+import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -49,8 +50,7 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.method.IParameter;
import ca.uhn.fhir.rest.method.MethodUtil;
-import ca.uhn.fhir.rest.method.Request;
-import ca.uhn.fhir.rest.param.ResourceParameter.Mode;
+import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.IResourceProvider;
@@ -103,7 +103,7 @@ public class ResourceParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
switch (myMode) {
case BODY:
try {
@@ -138,11 +138,11 @@ public class ResourceParameter implements IParameter {
return requestReader;
}
- static Reader createRequestReader(Request theRequest, byte[] theRequestContents) {
+ static Reader createRequestReader(RequestDetails theRequest, byte[] theRequestContents) {
return createRequestReader(theRequestContents, determineRequestCharset(theRequest));
}
- static Charset determineRequestCharset(Request theRequest) {
+ static Charset determineRequestCharset(RequestDetails theRequest) {
String ct = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
Charset charset = null;
@@ -156,7 +156,7 @@ public class ResourceParameter implements IParameter {
return charset;
}
- public static IBaseResource loadResourceFromRequest(Request theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding, Class extends IBaseResource> theResourceType) {
+ public static IBaseResource loadResourceFromRequest(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding, Class extends IBaseResource> theResourceType) {
FhirContext ctx = theRequest.getServer().getFhirContext();
final Charset charset = determineRequestCharset(theRequest);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/TransactionParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/TransactionParameter.java
index cf51eab2cb1..5cc912672d7 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/TransactionParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/TransactionParameter.java
@@ -40,7 +40,7 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.method.IParameter;
-import ca.uhn.fhir.rest.method.Request;
+import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
@@ -98,7 +98,7 @@ public class TransactionParameter implements IParameter {
}
@Override
- public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
// TODO: don't use a default encoding, just fail!
EncodingEnum encoding = RestfulServerUtils.determineRequestEncoding(theRequest);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
index dca1573ded1..72cd4ba7599 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
@@ -43,6 +43,7 @@ public class Constants {
public static final String CT_TEXT_WITH_UTF8 = CT_TEXT + "; charset=UTF-8";
public static final String CT_XML = "application/xml";
public static final String ENCODING_GZIP = "gzip";
+ public static final String EXTOP_VALIDATE = "$validate";
public static final String FORMAT_JSON = "json";
public static final Set FORMAT_VAL_JSON;
public static final Map FORMAT_VAL_TO_ENCODING;
@@ -91,13 +92,13 @@ public class Constants {
public static final String PARAM_FORMAT = "_format";
public static final String PARAM_HISTORY = "_history";
public static final String PARAM_INCLUDE = "_include";
- public static final String PARAM_REVINCLUDE = "_revinclude";
public static final String PARAM_NARRATIVE = "_narrative";
public static final String PARAM_PAGINGACTION = "_getpages";
public static final String PARAM_PAGINGOFFSET = "_getpagesoffset";
public static final String PARAM_PRETTY = "_pretty";
public static final String PARAM_PRETTY_VALUE_TRUE = "true";
public static final String PARAM_QUERY = "_query";
+ public static final String PARAM_REVINCLUDE = "_revinclude";
public static final String PARAM_SEARCH = "_search";
public static final String PARAM_SINCE = "_since";
public static final String PARAM_SORT = "_sort";
@@ -106,6 +107,8 @@ public class Constants {
public static final String PARAM_TAGS = "_tags";
public static final String PARAM_VALIDATE = "_validate";
public static final String PARAMQUALIFIER_MISSING = ":missing";
+ public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
+ public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
public static final String PARAMQUALIFIER_STRING_EXACT = ":exact";
public static final String PARAMQUALIFIER_TOKEN_TEXT = ":text";
public static final int STATUS_HTTP_200_OK = 200;
@@ -125,8 +128,9 @@ public class Constants {
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
public static final String URL_TOKEN_HISTORY = "_history";
public static final String URL_TOKEN_METADATA = "metadata";
- public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
- public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
+ public static final String EXTOP_VALIDATE_MODE = "mode";
+ public static final String EXTOP_VALIDATE_PROFILE = "profile";
+ public static final String EXTOP_VALIDATE_RESOURCE = "resource";
static {
Map valToEncoding = new HashMap();
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/ResourceBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/ResourceBinding.java
index 75d3c2ca945..363745ecf82 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/ResourceBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/ResourceBinding.java
@@ -24,7 +24,7 @@ import java.util.ArrayList;
import java.util.List;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
-import ca.uhn.fhir.rest.method.Request;
+import ca.uhn.fhir.rest.method.RequestDetails;
/**
* Created by dsotnikov on 2/25/2014.
@@ -44,7 +44,7 @@ public class ResourceBinding {
this.methods = methods;
}
- public BaseMethodBinding> getMethod(Request theRequest) throws Exception {
+ public BaseMethodBinding> getMethod(RequestDetails theRequest) {
if (null == methods) {
ourLog.warn("No methods exist for resource: {}", resourceName);
return null;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
index e24dca44224..b938514ae90 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
@@ -27,7 +27,16 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
@@ -37,17 +46,13 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
-import org.apache.commons.lang3.exception.ExceptionUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.ProvidedResourceScanner;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.Bundle;
-import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
-import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
-import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.Destroy;
import ca.uhn.fhir.rest.annotation.IdParam;
@@ -55,11 +60,9 @@ import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
import ca.uhn.fhir.rest.method.OtherOperationTypeEnum;
-import ca.uhn.fhir.rest.method.Request;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
-import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
@@ -426,7 +429,7 @@ public class RestfulServer extends HttpServlet {
return myServerVersion;
}
- private void handlePagingRequest(Request theRequest, HttpServletResponse theResponse, String thePagingAction) throws IOException {
+ private void handlePagingRequest(RequestDetails theRequest, HttpServletResponse theResponse, String thePagingAction) throws IOException {
IBundleProvider resultList = getPagingProvider().retrieveResultList(thePagingAction);
if (resultList == null) {
ourLog.info("Client requested unknown paging ID[{}]", thePagingAction);
@@ -496,7 +499,7 @@ public class RestfulServer extends HttpServlet {
return;
}
}
- RestfulServerUtils.streamResponseAsResource(this, theResponse, (IResource) resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase(), false);
+ RestfulServerUtils.streamResponseAsResource(this, theResponse, resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase(), false);
}
}
@@ -511,7 +514,7 @@ public class RestfulServer extends HttpServlet {
String fhirServerBase = null;
boolean requestIsBrowser = requestIsBrowser(theRequest);
- Request requestDetails = new Request();
+ RequestDetails requestDetails = new RequestDetails();
requestDetails.setServer(this);
try {
@@ -816,6 +819,7 @@ public class RestfulServer extends HttpServlet {
* (which extends {@link ServletException}), as this is a flag to the servlet container that the servlet
* is not usable.
*/
+ @SuppressWarnings("unused")
protected void initialize() throws ServletException {
// nothing by default
}
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 e21744e7d83..7dcde66f03a 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
@@ -40,9 +40,9 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
-import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseBinary;
+import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.FhirContext;
@@ -55,24 +55,264 @@ import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.IParser;
-import ca.uhn.fhir.rest.method.Request;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
public class RestfulServerUtils {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServerUtils.class);
- static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
- String countString = theRequest.getParameter(name);
- Integer count = null;
- if (isNotBlank(countString)) {
- try {
- count = Integer.parseInt(countString);
- } catch (NumberFormatException e) {
- ourLog.debug("Failed to parse _count value '{}': {}", countString, e);
+ public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
+ if (theResource instanceof IResource) {
+ TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) theResource);
+ if (tl == null) {
+ tl = new TagList();
+ ResourceMetadataKeyEnum.TAG_LIST.put((IResource) theResource, tl);
+ }
+
+ RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
+ String profile = nextDef.getResourceProfile(theServerBase);
+ if (isNotBlank(profile)) {
+ tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
}
}
- return count;
+ }
+
+ public static String createPagingLink(Set theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint) {
+ try {
+ StringBuilder b = new StringBuilder();
+ b.append(theServerBase);
+ b.append('?');
+ b.append(Constants.PARAM_PAGINGACTION);
+ b.append('=');
+ b.append(URLEncoder.encode(theSearchId, "UTF-8"));
+
+ b.append('&');
+ b.append(Constants.PARAM_PAGINGOFFSET);
+ b.append('=');
+ b.append(theOffset);
+ b.append('&');
+ b.append(Constants.PARAM_COUNT);
+ b.append('=');
+ b.append(theCount);
+ if (theResponseEncoding != null) {
+ b.append('&');
+ b.append(Constants.PARAM_FORMAT);
+ b.append('=');
+ b.append(theResponseEncoding.getRequestContentType());
+ }
+ if (thePrettyPrint) {
+ b.append('&');
+ b.append(Constants.PARAM_PRETTY);
+ b.append('=');
+ b.append(Constants.PARAM_PRETTY_VALUE_TRUE);
+ }
+
+ if (theIncludes != null) {
+ for (Include nextInclude : theIncludes) {
+ if (isNotBlank(nextInclude.getValue())) {
+ b.append('&');
+ b.append(Constants.PARAM_INCLUDE);
+ b.append('=');
+ b.append(URLEncoder.encode(nextInclude.getValue(), "UTF-8"));
+ }
+ }
+ }
+
+ return b.toString();
+ } catch (UnsupportedEncodingException e) {
+ throw new Error("UTF-8 not supported", e);// should not happen
+ }
+ }
+
+ public static RestfulServer.NarrativeModeEnum determineNarrativeMode(RequestDetails theRequest) {
+ Map requestParams = theRequest.getParameters();
+ String[] narrative = requestParams.get(Constants.PARAM_NARRATIVE);
+ RestfulServer.NarrativeModeEnum narrativeMode = null;
+ if (narrative != null && narrative.length > 0) {
+ try {
+ narrativeMode = RestfulServer.NarrativeModeEnum.valueOfCaseInsensitive(narrative[0]);
+ } catch (IllegalArgumentException e) {
+ ourLog.debug("Invalid {} parameger: {}", Constants.PARAM_NARRATIVE, narrative[0]);
+ narrativeMode = null;
+ }
+ }
+ if (narrativeMode == null) {
+ narrativeMode = RestfulServer.NarrativeModeEnum.NORMAL;
+ }
+ return narrativeMode;
+ }
+
+ public static EncodingEnum determineRequestEncoding(RequestDetails theReq) {
+ EncodingEnum retVal = determineRequestEncodingNoDefault(theReq);
+ if (retVal != null) {
+ return retVal;
+ }
+ return EncodingEnum.XML;
+ }
+
+ public static EncodingEnum determineRequestEncodingNoDefault(RequestDetails theReq) {
+ EncodingEnum retVal = null;
+ Enumeration acceptValues = theReq.getServletRequest().getHeaders(Constants.HEADER_CONTENT_TYPE);
+ if (acceptValues != null) {
+ while (acceptValues.hasMoreElements() && retVal == null) {
+ String nextAcceptHeaderValue = acceptValues.nextElement();
+ if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
+ for (String nextPart : nextAcceptHeaderValue.split(",")) {
+ int scIdx = nextPart.indexOf(';');
+ if (scIdx == 0) {
+ continue;
+ }
+ if (scIdx != -1) {
+ nextPart = nextPart.substring(0, scIdx);
+ }
+ nextPart = nextPart.trim();
+ retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
+ if (retVal != null) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return retVal;
+ }
+
+ public static EncodingEnum determineResponseEncodingNoDefault(HttpServletRequest theReq) {
+ String[] format = theReq.getParameterValues(Constants.PARAM_FORMAT);
+ if (format != null) {
+ for (String nextFormat : format) {
+ EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextFormat);
+ if (retVal != null) {
+ return retVal;
+ }
+ }
+ }
+
+ Enumeration acceptValues = theReq.getHeaders(Constants.HEADER_ACCEPT);
+ if (acceptValues != null) {
+ while (acceptValues.hasMoreElements()) {
+ String nextAcceptHeaderValue = acceptValues.nextElement();
+ if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
+ for (String nextPart : nextAcceptHeaderValue.split(",")) {
+ int scIdx = nextPart.indexOf(';');
+ if (scIdx == 0) {
+ continue;
+ }
+ if (scIdx != -1) {
+ nextPart = nextPart.substring(0, scIdx);
+ }
+ nextPart = nextPart.trim();
+ EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
+ if (retVal != null) {
+ return retVal;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Determine whether a response should be given in JSON or XML format based on the incoming HttpServletRequest's "_format"
parameter and "Accept:"
HTTP header.
+ */
+ public static EncodingEnum determineResponseEncodingWithDefault(RestfulServer theServer, HttpServletRequest theReq) {
+ EncodingEnum retVal = determineResponseEncodingNoDefault(theReq);
+ if (retVal == null) {
+ retVal = theServer.getDefaultResponseEncoding();
+ }
+ return retVal;
+ }
+
+ public static Integer extractCountParameter(HttpServletRequest theRequest) {
+ return RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_COUNT);
+ }
+
+ public static IParser getNewParser(FhirContext theContext, EncodingEnum theResponseEncoding, boolean thePrettyPrint, RestfulServer.NarrativeModeEnum theNarrativeMode) {
+ IParser parser;
+ switch (theResponseEncoding) {
+ case JSON:
+ parser = theContext.newJsonParser();
+ break;
+ case XML:
+ default:
+ parser = theContext.newXmlParser();
+ break;
+ }
+ return parser.setPrettyPrint(thePrettyPrint).setSuppressNarratives(theNarrativeMode == RestfulServer.NarrativeModeEnum.SUPPRESS);
+ }
+
+ static Writer getWriter(HttpServletResponse theHttpResponse, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
+ Writer writer;
+ if (theRespondGzip) {
+ theHttpResponse.addHeader(Constants.HEADER_CONTENT_ENCODING, Constants.ENCODING_GZIP);
+ writer = new OutputStreamWriter(new GZIPOutputStream(theHttpResponse.getOutputStream()), "UTF-8");
+ } else {
+ writer = theHttpResponse.getWriter();
+ }
+ return writer;
+ }
+
+ public static boolean prettyPrintResponse(RestfulServer theServer, RequestDetails theRequest) {
+ Map requestParams = theRequest.getParameters();
+ String[] pretty = requestParams.get(Constants.PARAM_PRETTY);
+ boolean prettyPrint;
+ if (pretty != null && pretty.length > 0) {
+ if (Constants.PARAM_PRETTY_VALUE_TRUE.equals(pretty[0])) {
+ prettyPrint = true;
+ } else {
+ prettyPrint = false;
+ }
+ } else {
+ prettyPrint = theServer.isDefaultPrettyPrint();
+ Enumeration acceptValues = theRequest.getServletRequest().getHeaders(Constants.HEADER_ACCEPT);
+ if (acceptValues != null) {
+ while (acceptValues.hasMoreElements()) {
+ String nextAcceptHeaderValue = acceptValues.nextElement();
+ if (nextAcceptHeaderValue.contains("pretty=true")) {
+ prettyPrint = true;
+ }
+ }
+ }
+ }
+ return prettyPrint;
+ }
+
+ public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, EncodingEnum theResponseEncoding, String theServerBase,
+ boolean thePrettyPrint, RestfulServer.NarrativeModeEnum theNarrativeMode, boolean theRespondGzip, boolean theRequestIsBrowser) throws IOException {
+ assert !theServerBase.endsWith("/");
+
+ theHttpResponse.setStatus(200);
+
+ EncodingEnum responseEncoding = theResponseEncoding != null ? theResponseEncoding : theServer.getDefaultResponseEncoding();
+
+ if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
+ theHttpResponse.setContentType(responseEncoding.getBrowserFriendlyBundleContentType());
+ } else if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
+ theHttpResponse.setContentType(Constants.CT_HTML);
+ } else {
+ theHttpResponse.setContentType(responseEncoding.getBundleContentType());
+ }
+
+ theHttpResponse.setCharacterEncoding(Constants.CHARSETNAME_UTF_8);
+
+ theServer.addHeadersToResponse(theHttpResponse);
+
+ Writer writer = RestfulServerUtils.getWriter(theHttpResponse, theRespondGzip);
+ try {
+ if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
+ for (IResource next : bundle.toListOfResources()) {
+ writer.append(next.getText().getDiv().getValueAsString());
+ writer.append(" ");
+ }
+ } else {
+ IParser parser = RestfulServerUtils.getNewParser(theServer.getFhirContext(), responseEncoding, thePrettyPrint, theNarrativeMode);
+ parser.setServerBaseUrl(theServerBase);
+ parser.encodeBundleToWriter(bundle, writer);
+ }
+ } finally {
+ writer.close();
+ }
}
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IBaseResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
@@ -168,258 +408,17 @@ public class RestfulServerUtils {
}
}
- public static boolean prettyPrintResponse(RestfulServer theServer, RequestDetails theRequest) {
- Map requestParams = theRequest.getParameters();
- String[] pretty = requestParams.get(Constants.PARAM_PRETTY);
- boolean prettyPrint;
- if (pretty != null && pretty.length > 0) {
- if (Constants.PARAM_PRETTY_VALUE_TRUE.equals(pretty[0])) {
- prettyPrint = true;
- } else {
- prettyPrint = false;
- }
- } else {
- prettyPrint = theServer.isDefaultPrettyPrint();
- Enumeration acceptValues = ((Request)theRequest).getServletRequest().getHeaders(Constants.HEADER_ACCEPT);
- if (acceptValues != null) {
- while (acceptValues.hasMoreElements()) {
- String nextAcceptHeaderValue = acceptValues.nextElement();
- if (nextAcceptHeaderValue.contains("pretty=true")) {
- prettyPrint = true;
- }
- }
- }
- }
- return prettyPrint;
- }
-
- static Writer getWriter(HttpServletResponse theHttpResponse, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
- Writer writer;
- if (theRespondGzip) {
- theHttpResponse.addHeader(Constants.HEADER_CONTENT_ENCODING, Constants.ENCODING_GZIP);
- writer = new OutputStreamWriter(new GZIPOutputStream(theHttpResponse.getOutputStream()), "UTF-8");
- } else {
- writer = theHttpResponse.getWriter();
- }
- return writer;
- }
-
- public static EncodingEnum determineRequestEncoding(Request theReq) {
- EncodingEnum retVal = determineRequestEncodingNoDefault(theReq);
- if (retVal != null) {
- return retVal;
- }
- return EncodingEnum.XML;
- }
-
- public static EncodingEnum determineRequestEncodingNoDefault(Request theReq) {
- EncodingEnum retVal = null;
- Enumeration acceptValues = theReq.getServletRequest().getHeaders(Constants.HEADER_CONTENT_TYPE);
- if (acceptValues != null) {
- while (acceptValues.hasMoreElements() && retVal == null) {
- String nextAcceptHeaderValue = acceptValues.nextElement();
- if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
- for (String nextPart : nextAcceptHeaderValue.split(",")) {
- int scIdx = nextPart.indexOf(';');
- if (scIdx == 0) {
- continue;
- }
- if (scIdx != -1) {
- nextPart = nextPart.substring(0, scIdx);
- }
- nextPart = nextPart.trim();
- retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
- if (retVal != null) {
- break;
- }
- }
- }
- }
- }
- return retVal;
- }
-
- public static String createPagingLink(Set theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint) {
- try {
- StringBuilder b = new StringBuilder();
- b.append(theServerBase);
- b.append('?');
- b.append(Constants.PARAM_PAGINGACTION);
- b.append('=');
- b.append(URLEncoder.encode(theSearchId, "UTF-8"));
-
- b.append('&');
- b.append(Constants.PARAM_PAGINGOFFSET);
- b.append('=');
- b.append(theOffset);
- b.append('&');
- b.append(Constants.PARAM_COUNT);
- b.append('=');
- b.append(theCount);
- if (theResponseEncoding != null) {
- b.append('&');
- b.append(Constants.PARAM_FORMAT);
- b.append('=');
- b.append(theResponseEncoding.getRequestContentType());
- }
- if (thePrettyPrint) {
- b.append('&');
- b.append(Constants.PARAM_PRETTY);
- b.append('=');
- b.append(Constants.PARAM_PRETTY_VALUE_TRUE);
- }
-
- if (theIncludes != null) {
- for (Include nextInclude : theIncludes) {
- if (isNotBlank(nextInclude.getValue())) {
- b.append('&');
- b.append(Constants.PARAM_INCLUDE);
- b.append('=');
- b.append(URLEncoder.encode(nextInclude.getValue(), "UTF-8"));
- }
- }
- }
-
- return b.toString();
- } catch (UnsupportedEncodingException e) {
- throw new Error("UTF-8 not supported", e);// should not happen
- }
- }
-
- public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
- if (theResource instanceof IResource) {
- TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) theResource);
- if (tl == null) {
- tl = new TagList();
- ResourceMetadataKeyEnum.TAG_LIST.put((IResource) theResource, tl);
- }
-
- RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
- String profile = nextDef.getResourceProfile(theServerBase);
- if (isNotBlank(profile)) {
- tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
- }
- }
- }
-
- public static RestfulServer.NarrativeModeEnum determineNarrativeMode(RequestDetails theRequest) {
- Map requestParams = theRequest.getParameters();
- String[] narrative = requestParams.get(Constants.PARAM_NARRATIVE);
- RestfulServer.NarrativeModeEnum narrativeMode = null;
- if (narrative != null && narrative.length > 0) {
+ static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
+ String countString = theRequest.getParameter(name);
+ Integer count = null;
+ if (isNotBlank(countString)) {
try {
- narrativeMode = RestfulServer.NarrativeModeEnum.valueOfCaseInsensitive(narrative[0]);
- } catch (IllegalArgumentException e) {
- ourLog.debug("Invalid {} parameger: {}", Constants.PARAM_NARRATIVE, narrative[0]);
- narrativeMode = null;
+ count = Integer.parseInt(countString);
+ } catch (NumberFormatException e) {
+ ourLog.debug("Failed to parse _count value '{}': {}", countString, e);
}
}
- if (narrativeMode == null) {
- narrativeMode = RestfulServer.NarrativeModeEnum.NORMAL;
- }
- return narrativeMode;
- }
-
- /**
- * Determine whether a response should be given in JSON or XML format based on the incoming HttpServletRequest's "_format"
parameter and "Accept:"
HTTP header.
- */
- public static EncodingEnum determineResponseEncodingWithDefault(RestfulServer theServer, HttpServletRequest theReq) {
- EncodingEnum retVal = determineResponseEncodingNoDefault(theReq);
- if (retVal == null) {
- retVal = theServer.getDefaultResponseEncoding();
- }
- return retVal;
- }
-
- public static IParser getNewParser(FhirContext theContext, EncodingEnum theResponseEncoding, boolean thePrettyPrint, RestfulServer.NarrativeModeEnum theNarrativeMode) {
- IParser parser;
- switch (theResponseEncoding) {
- case JSON:
- parser = theContext.newJsonParser();
- break;
- case XML:
- default:
- parser = theContext.newXmlParser();
- break;
- }
- return parser.setPrettyPrint(thePrettyPrint).setSuppressNarratives(theNarrativeMode == RestfulServer.NarrativeModeEnum.SUPPRESS);
- }
-
- public static EncodingEnum determineResponseEncodingNoDefault(HttpServletRequest theReq) {
- String[] format = theReq.getParameterValues(Constants.PARAM_FORMAT);
- if (format != null) {
- for (String nextFormat : format) {
- EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextFormat);
- if (retVal != null) {
- return retVal;
- }
- }
- }
-
- Enumeration acceptValues = theReq.getHeaders(Constants.HEADER_ACCEPT);
- if (acceptValues != null) {
- while (acceptValues.hasMoreElements()) {
- String nextAcceptHeaderValue = acceptValues.nextElement();
- if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
- for (String nextPart : nextAcceptHeaderValue.split(",")) {
- int scIdx = nextPart.indexOf(';');
- if (scIdx == 0) {
- continue;
- }
- if (scIdx != -1) {
- nextPart = nextPart.substring(0, scIdx);
- }
- nextPart = nextPart.trim();
- EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
- if (retVal != null) {
- return retVal;
- }
- }
- }
- }
- }
- return null;
- }
-
- public static Integer extractCountParameter(HttpServletRequest theRequest) {
- return RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_COUNT);
- }
-
- public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, EncodingEnum theResponseEncoding, String theServerBase,
- boolean thePrettyPrint, RestfulServer.NarrativeModeEnum theNarrativeMode, boolean theRespondGzip, boolean theRequestIsBrowser) throws IOException {
- assert !theServerBase.endsWith("/");
-
- theHttpResponse.setStatus(200);
-
- EncodingEnum responseEncoding = theResponseEncoding != null ? theResponseEncoding : theServer.getDefaultResponseEncoding();
-
- if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
- theHttpResponse.setContentType(responseEncoding.getBrowserFriendlyBundleContentType());
- } else if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
- theHttpResponse.setContentType(Constants.CT_HTML);
- } else {
- theHttpResponse.setContentType(responseEncoding.getBundleContentType());
- }
-
- theHttpResponse.setCharacterEncoding(Constants.CHARSETNAME_UTF_8);
-
- theServer.addHeadersToResponse(theHttpResponse);
-
- Writer writer = RestfulServerUtils.getWriter(theHttpResponse, theRespondGzip);
- try {
- if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
- for (IResource next : bundle.toListOfResources()) {
- writer.append(next.getText().getDiv().getValueAsString());
- writer.append(" ");
- }
- } else {
- IParser parser = RestfulServerUtils.getNewParser(theServer.getFhirContext(), responseEncoding, thePrettyPrint, theNarrativeMode);
- parser.setServerBaseUrl(theServerBase);
- parser.encodeBundleToWriter(bundle, writer);
- }
- } finally {
- writer.close();
- }
+ return count;
}
// public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/SearchParameterMap.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/SearchParameterMap.java
index 52ed1f8e88c..86dc46bde84 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/SearchParameterMap.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/SearchParameterMap.java
@@ -38,6 +38,8 @@ import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
+import ca.uhn.fhir.rest.param.UriAndListParam;
+import ca.uhn.fhir.rest.param.UriOrListParam;
public class SearchParameterMap extends LinkedHashMap> {
@@ -71,10 +73,19 @@ public class SearchParameterMap extends LinkedHashMapThe resource ID associated with this request, or the resource name if the request applies to a type but not an instance, or "" otherwise
*
*
+ * ${operationName}
+ * If the request is an extended operation (e.g. "$validate") this value will be the operation name, or "" otherwise
+ *
+ *
* ${operationType}
- * A code indicating the operation type for this request, e.g. "read", "history-instance", etc.)
+ * A code indicating the operation type for this request, e.g. "read", "history-instance", "extended-operation-instance", etc.)
*
*
* ${remoteAddr}
@@ -69,6 +75,10 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
* The HTTP request parameters (or "")
*
*
+ * ${responseEncodingNoDefault}
+ * The encoding format requested by the client via the _format parameter or the Accept header. Value will be "json" or "xml", or "" if the client did not explicitly request a format
+ *
+ *
* ${servletPath}
* The part of thre requesting URL that corresponds to the particular Servlet being called (see {@link HttpServletRequest#getServletPath()})
*
@@ -125,6 +135,11 @@ public class LoggingInterceptor extends InterceptorAdapter {
@Override
public String lookup(String theKey) {
+
+ /*
+ * TODO: this method could be made more efficient through some sort of lookup map
+ */
+
if ("operationType".equals(theKey)) {
if (myRequestDetails.getResourceOperationType() != null) {
return myRequestDetails.getResourceOperationType().getCode();
@@ -136,6 +151,19 @@ public class LoggingInterceptor extends InterceptorAdapter {
return myRequestDetails.getOtherOperationType().getCode();
}
return "";
+ } else if ("operationName".equals(theKey)) {
+ if (myRequestDetails.getOtherOperationType() != null) {
+ switch (myRequestDetails.getOtherOperationType()) {
+ case EXTENDED_OPERATION_INSTANCE:
+ case EXTENDED_OPERATION_SERVER:
+ case EXTENDED_OPERATION_TYPE:
+ return myRequestDetails.getOperation();
+ default:
+ return "";
+ }
+ } else {
+ return "";
+ }
} else if ("id".equals(theKey)) {
if (myRequestDetails.getId() != null) {
return myRequestDetails.getId().getValue();
@@ -175,7 +203,15 @@ public class LoggingInterceptor extends InterceptorAdapter {
return StringUtils.defaultString(val);
} else if (theKey.startsWith("remoteAddr")) {
return StringUtils.defaultString(myRequest.getRemoteAddr());
+ } else if (theKey.equals("responseEncodingNoDefault")) {
+ EncodingEnum encoding = RestfulServerUtils.determineResponseEncodingNoDefault(myRequest);
+ if (encoding != null) {
+ return encoding.name();
+ } else {
+ return "";
+ }
}
+
return "!VAL!";
}
}
diff --git a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseConformance.java b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseConformance.java
index 320eb4ee123..21cf10d5c39 100644
--- a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseConformance.java
+++ b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseConformance.java
@@ -1,5 +1,25 @@
package org.hl7.fhir.instance.model.api;
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2015 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%
+ */
+
public interface IBaseConformance extends IBaseResource {
diff --git a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseXhtml.java b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseXhtml.java
index 03f6a65758d..9ce67695516 100644
--- a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseXhtml.java
+++ b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseXhtml.java
@@ -1,5 +1,25 @@
package org.hl7.fhir.instance.model.api;
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2015 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%
+ */
+
public interface IBaseXhtml extends IPrimitiveType {
diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml
index bba2f793f0f..493fcad36c3 100644
--- a/hapi-fhir-jpaserver-base/pom.xml
+++ b/hapi-fhir-jpaserver-base/pom.xml
@@ -77,6 +77,19 @@
test
+
+ com.phloc
+ phloc-schematron
+ ${phloc_schematron_version}
+ test
+
+
+ com.phloc
+ phloc-commons
+ ${phloc_commons_version}
+ test
+
+
org.jscience
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaResourceProviderDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaResourceProviderDstu2.java
index 59201bf602e..114519ed6c8 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaResourceProviderDstu2.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaResourceProviderDstu2.java
@@ -24,9 +24,16 @@ import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.model.api.IResource;
+import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
+import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
+import ca.uhn.fhir.model.dstu2.resource.OperationOutcome.Issue;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
+import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
+import ca.uhn.fhir.model.dstu2.valueset.IssueTypeEnum;
import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.parser.IParserErrorHandler;
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Delete;
@@ -35,8 +42,14 @@ import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Update;
+import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.ValidationModeEnum;
+import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
+import ca.uhn.fhir.validation.FhirValidator;
+import ca.uhn.fhir.validation.ValidationResult;
public class JpaResourceProviderDstu2 extends BaseJpaResourceProvider {
@@ -78,25 +91,6 @@ public class JpaResourceProviderDstu2 extends BaseJpaResour
}
}
- @Update
- public MethodOutcome update(HttpServletRequest theRequest, @ResourceParam T theResource, @IdParam IdDt theId, @ConditionalUrlParam String theConditional) {
- startRequest(theRequest);
- try {
- if (theConditional != null) {
- return getDao().update(theResource, theConditional);
- } else {
- theResource.setId(theId);
- return getDao().update(theResource);
- }
- } catch (ResourceNotFoundException e) {
- ourLog.info("Can't update resource with ID[" + theId.getValue() + "] because it doesn't exist, going to create it instead");
- theResource.setId(theId);
- return getDao().create(theResource);
- } finally {
- endRequest(theRequest);
- }
- }
-
//@formatter:off
@Operation(name="$meta", idempotent=true, returnParameters= {
@OperationParam(name="return", type=MetaDt.class)
@@ -141,4 +135,67 @@ public class JpaResourceProviderDstu2 extends BaseJpaResour
return parameters;
}
+ @Update
+ public MethodOutcome update(HttpServletRequest theRequest, @ResourceParam T theResource, @IdParam IdDt theId, @ConditionalUrlParam String theConditional) {
+ startRequest(theRequest);
+ try {
+ if (theConditional != null) {
+ return getDao().update(theResource, theConditional);
+ } else {
+ theResource.setId(theId);
+ return getDao().update(theResource);
+ }
+ } catch (ResourceNotFoundException e) {
+ ourLog.info("Can't update resource with ID[" + theId.getValue() + "] because it doesn't exist, going to create it instead");
+ theResource.setId(theId);
+ return getDao().create(theResource);
+ } finally {
+ endRequest(theRequest);
+ }
+ }
+
+ @Validate
+ public MethodOutcome validate(@ResourceParam T theResource, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
+ @Validate.Profile String theProfile) {
+
+ final OperationOutcome oo = new OperationOutcome();
+
+ IParser parser = theEncoding.newParser(getContext());
+ parser.setParserErrorHandler(new IParserErrorHandler() {
+
+ @Override
+ public void unknownAttribute(IParseLocation theLocation, String theAttributeName) {
+ oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDetails("Unknown attribute found: " + theAttributeName);
+ }
+
+ @Override
+ public void unknownElement(IParseLocation theLocation, String theElementName) {
+ oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDetails("Unknown element found: " + theElementName);
+ }
+ });
+
+ FhirValidator validator = getContext().newValidator();
+ validator.setValidateAgainstStandardSchema(true);
+ validator.setValidateAgainstStandardSchematron(true);
+ ValidationResult result = validator.validateWithResult(theResource);
+ for (BaseIssue next : result.getOperationOutcome().getIssue()) {
+ oo.getIssue().add((Issue) next);
+ }
+
+ if (oo.getIssue().size() > 0) {
+ /*
+ * It is also possible to pass an OperationOutcome resource to the UnprocessableEntityException if you want to return a custom populated OperationOutcome. Otherwise, a simple one is
+ * created using the string supplied below.
+ */
+ throw new UnprocessableEntityException("Validation failed", oo);
+ }
+
+ // This method returns a MethodOutcome object
+ MethodOutcome retVal = new MethodOutcome();
+ oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Validation succeeded");
+ retVal.setOperationOutcome(oo);
+
+ return retVal;
+ }
+
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java
index 8f68a2f1628..805663e16db 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java
@@ -23,6 +23,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
@@ -69,6 +70,7 @@ import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
+import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UnsignedIntDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
@@ -91,59 +93,57 @@ public class ResourceProviderDstu2Test {
private static ClassPathXmlApplicationContext ourAppCtx;
private static IGenericClient ourClient;
+ private static DaoConfig ourDaoConfig;
private static FhirContext ourFhirCtx;
+ private static CloseableHttpClient ourHttpClient;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2Test.class);
+ private static IFhirResourceDao ourOrganizationDao;
+ private static int ourPort;
// private static IFhirResourceDao ourObservationDao;
// private static IFhirResourceDao ourPatientDao;
// private static IFhirResourceDao ourQuestionnaireDao;
private static Server ourServer;
- private static IFhirResourceDao ourOrganizationDao;
- private static DaoConfig ourDaoConfig;
- private static CloseableHttpClient ourHttpClient;
private static String ourServerBase;
- private static int ourPort;
// private static JpaConformanceProvider ourConfProvider;
- /**
- * Test for issue #60
- */
- @Test
- public void testStoreUtf8Characters() throws Exception {
- Organization org = new Organization();
- org.setName("測試醫院");
- org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
- IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
-
- // Read back directly from the DAO
- {
- Organization returned = ourOrganizationDao.read(orgId);
- String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
- ourLog.info(val);
- assertThat(val, containsString(""));
+ private void delete(String theResourceType, String theParamName, String theParamValue) {
+ Bundle resources = ourClient.search().forResource(theResourceType).where(new StringClientParam(theParamName).matches().value(theParamValue)).execute();
+ for (IResource next : resources.toListOfResources()) {
+ ourLog.info("Deleting resource: {}", next.getId());
+ ourClient.delete().resource(next).execute();
}
- // Read back through the HTTP API
- {
- Organization returned = ourClient.read(Organization.class, orgId);
- String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
- ourLog.info(val);
- assertThat(val, containsString(""));
+ }
+
+ private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue) {
+ Bundle resources = ourClient.search().forResource(theResourceType).where(new TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
+ for (IResource next : resources.toListOfResources()) {
+ ourLog.info("Deleting resource: {}", next.getId());
+ ourClient.delete().resource(next).execute();
}
}
@Test
- public void testCreateResourceWithNumericId() throws IOException {
- String resource = " ";
+ public void testCountParam() throws Exception {
+ // NB this does not get used- The paging provider has its own limits built in
+ ourDaoConfig.setHardSearchLimit(100);
- HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
- post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
-
- CloseableHttpResponse response = ourHttpClient.execute(post);
- try {
- assertEquals(400, response.getStatusLine().getStatusCode());
- } finally {
- response.close();
+ List resources = new ArrayList();
+ for (int i = 0; i < 100; i++) {
+ Organization org = new Organization();
+ org.setName("rpdstu2_testCountParam_01");
+ resources.add(org);
}
+ ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
+
+ Bundle found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(10).execute();
+ assertEquals(100, found.getTotalResults().getValue().intValue());
+ assertEquals(10, found.getEntries().size());
+
+ found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(999).execute();
+ assertEquals(100, found.getTotalResults().getValue().intValue());
+ assertEquals(50, found.getEntries().size());
+
}
@Test
@@ -183,37 +183,56 @@ public class ResourceProviderDstu2Test {
}
@Test
- public void testUpdateResourceConditional() throws IOException {
- String methodName = "testUpdateResourceConditional";
+ public void testCreateResourceWithNumericId() throws IOException {
+ String resource = " ";
- Patient pt = new Patient();
- pt.addName().addFamily(methodName);
- String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
-
- HttpPost post = new HttpPost(ourServerBase + "/Patient?name=" + methodName);
+ HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
- CloseableHttpResponse response = ourHttpClient.execute(post);
- IdDt id;
- try {
- assertEquals(201, response.getStatusLine().getStatusCode());
- String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
- assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
- id = new IdDt(newIdString);
- } finally {
- response.close();
- }
- HttpPut put = new HttpPut(ourServerBase + "/Patient?name=" + methodName);
- put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
- response = ourHttpClient.execute(put);
+ CloseableHttpResponse response = ourHttpClient.execute(post);
try {
- assertEquals(200, response.getStatusLine().getStatusCode());
- IdDt newId = new IdDt(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue());
- assertEquals(id.toVersionless(), newId.toVersionless()); // version shouldn't match for conditional update
- assertNotEquals(id, newId);
+ assertEquals(400, response.getStatusLine().getStatusCode());
} finally {
response.close();
}
+ }
+
+ @Test
+ public void testDeepChaining() {
+ delete("Location", Location.SP_NAME, "testDeepChainingL1");
+ delete("Location", Location.SP_NAME, "testDeepChainingL2");
+ deleteToken("Encounter", Encounter.SP_IDENTIFIER, "urn:foo", "testDeepChainingE1");
+
+ Location l1 = new Location();
+ l1.getNameElement().setValue("testDeepChainingL1");
+ IdDt l1id = ourClient.create().resource(l1).execute().getId();
+
+ Location l2 = new Location();
+ l2.getNameElement().setValue("testDeepChainingL2");
+ l2.getPartOf().setReference(l1id.toVersionless().toUnqualified());
+ IdDt l2id = ourClient.create().resource(l2).execute().getId();
+
+ Encounter e1 = new Encounter();
+ e1.addIdentifier().setSystem("urn:foo").setValue("testDeepChainingE1");
+ e1.getStatusElement().setValueAsEnum(EncounterStateEnum.IN_PROGRESS);
+ e1.getClassElementElement().setValueAsEnum(EncounterClassEnum.HOME);
+ ca.uhn.fhir.model.dstu2.resource.Encounter.Location location = e1.addLocation();
+ location.getLocation().setReference(l2id.toUnqualifiedVersionless());
+ location.setPeriod(new PeriodDt().setStartWithSecondsPrecision(new Date()).setEndWithSecondsPrecision(new Date()));
+ IdDt e1id = ourClient.create().resource(e1).execute().getId();
+
+ //@formatter:off
+ Bundle res = ourClient.search()
+ .forResource(Encounter.class)
+ .where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1"))
+ .include(Encounter.INCLUDE_LOCATION)
+ .include(Location.INCLUDE_PARTOF)
+ .execute();
+ //@formatter:on
+
+ assertEquals(3, res.size());
+ assertEquals(1, res.getResources(Encounter.class).size());
+ assertEquals(e1id.toUnqualifiedVersionless(), res.getResources(Encounter.class).get(0).getId().toUnqualifiedVersionless());
}
@@ -325,184 +344,62 @@ public class ResourceProviderDstu2Test {
}
/**
- * Test for issue #60
+ * See issue #52
*/
@Test
- public void testReadAllInstancesOfType() throws Exception {
- Patient pat;
+ public void testDiagnosticOrderResources() throws Exception {
+ IGenericClient client = ourClient;
- pat = new Patient();
- pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_01");
- ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
+ int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size();
- pat = new Patient();
- pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_02");
- ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
+ DiagnosticOrder res = new DiagnosticOrder();
+ res.addIdentifier().setSystem("urn:foo").setValue("123");
+
+ client.create().resource(res).execute();
+
+ int newSize = client.search().forResource(DiagnosticOrder.class).execute().size();
+
+ assertEquals(1, newSize - initialSize);
- {
- Bundle returned = ourClient.search().forResource(Patient.class).encodedXml().execute();
- assertThat(returned.size(), greaterThan(1));
- assertEquals(BundleTypeEnum.SEARCHSET, returned.getType().getValueAsEnum());
- }
- {
- Bundle returned = ourClient.search().forResource(Patient.class).encodedJson().execute();
- assertThat(returned.size(), greaterThan(1));
- }
}
+ /**
+ * See issue #52
+ */
@Test
- public void testSearchBundleDoesntIncludeTextElement() throws Exception {
- HttpGet read = new HttpGet(ourServerBase + "/Patient?_format=json");
- CloseableHttpResponse response = ourHttpClient.execute(read);
- try {
- String text = IOUtils.toString(response.getEntity().getContent());
- ourLog.info(text);
- assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatusLine().getStatusCode());
- assertThat(text, not(containsString("\"text\",\"type\"")));
- } finally {
- response.close();
- }
+ public void testDocumentManifestResources() throws Exception {
+ ourFhirCtx.getResourceDefinition(Practitioner.class);
+ ourFhirCtx.getResourceDefinition(ca.uhn.fhir.model.dstu.resource.DocumentManifest.class);
+
+ IGenericClient client = ourClient;
+
+ int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
+
+ String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentmanifest.json"));
+ client.create().resource(resBody).execute();
+
+ int newSize = client.search().forResource(DocumentManifest.class).execute().size();
+
+ assertEquals(1, newSize - initialSize);
+
}
+ /**
+ * See issue #52
+ */
@Test
- public void testSearchWithInclude() throws Exception {
- Organization org = new Organization();
- org.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude01");
- IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
+ public void testDocumentReferenceResources() throws Exception {
+ IGenericClient client = ourClient;
- Patient pat = new Patient();
- pat.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude02");
- pat.getManagingOrganization().setReference(orgId);
- ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
+ int initialSize = client.search().forResource(DocumentReference.class).execute().size();
- //@formatter:off
- Bundle found = ourClient
- .search()
- .forResource(Patient.class)
- .where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system:rpdstu2","testSearchWithInclude02"))
- .include(Patient.INCLUDE_ORGANIZATION)
- .prettyPrint()
- .execute();
- //@formatter:on
+ String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentreference.json"));
+ client.create().resource(resBody).execute();
- assertEquals(2, found.size());
- assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
- assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum());
- assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
- assertThat(found.getEntries().get(0).getResource().getText().getDiv().getValueAsString(), containsString(" resources = new ArrayList();
- for (int i = 0; i < 20; i++) {
- Organization org = new Organization();
- org.setName(methodName + "_0" + i);
- resources.add(org);
- }
- ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
-
- Organization org = new Organization();
- org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
- org.setName(methodName + "name");
- IdDt orgNotMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
-
- org = new Organization();
- org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
- IdDt orgMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
-
- {
- //@formatter:off
- Bundle found = ourClient
- .search()
- .forResource(Organization.class)
- .where(Organization.NAME.isMissing(false))
- .limitTo(100)
- .prettyPrint()
- .execute();
- //@formatter:on
-
- List list = toIdListUnqualifiedVersionless(found);
- ourLog.info(methodName + ": " + list.toString());
- assertThat("Wanted " + orgNotMissing + " but got: " + list, list, containsInRelativeOrder(orgNotMissing));
- assertThat(list, not(containsInRelativeOrder(orgMissing)));
- }
-
- //@formatter:off
- Bundle found = ourClient
- .search()
- .forResource(Organization.class)
- .where(Organization.NAME.isMissing(true))
- .limitTo(100)
- .prettyPrint()
- .execute();
- //@formatter:on
-
- List list = toIdListUnqualifiedVersionless(found);
- ourLog.info(methodName + " found: " + list.toString() + " - Wanted " + orgMissing + " but not " + orgNotMissing);
- assertThat(list, not(containsInRelativeOrder(orgNotMissing)));
- assertThat("Wanted " + orgMissing + " but found: " + list, list, containsInRelativeOrder(orgMissing));
- }
-
- private List toIdListUnqualifiedVersionless(Bundle found) {
- List list = new ArrayList();
- for (BundleEntry next : found.getEntries()) {
- list.add(next.getResource().getId().toUnqualifiedVersionless());
- }
- return list;
- }
-
- @Test
- public void testEverythingOperation() throws Exception {
- String methodName = "testEverythingOperation";
-
- Organization org1 = new Organization();
- org1.setName(methodName + "1");
- IdDt orgId1 = ourClient.create().resource(org1).execute().getId();
-
- Patient p = new Patient();
- p.addName().addFamily(methodName);
- p.getManagingOrganization().setReference(orgId1);
- IdDt patientId = ourClient.create().resource(p).execute().getId();
-
- Organization org2 = new Organization();
- org2.setName(methodName + "1");
- IdDt orgId2 = ourClient.create().resource(org2).execute().getId();
-
- Device dev = new Device();
- dev.setModel(methodName);
- dev.getOwner().setReference(orgId2);
- IdDt devId = ourClient.create().resource(dev).execute().getId();
-
- Observation obs = new Observation();
- obs.getSubject().setReference(patientId);
- obs.getDevice().setReference(devId);
- IdDt obsId = ourClient.create().resource(obs).execute().getId();
-
- Encounter enc = new Encounter();
- enc.getPatient().setReference(patientId);
- IdDt encId = ourClient.create().resource(enc).execute().getId();
-
- Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
- ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
-
- Set ids = new HashSet();
- for (Entry next : b.getEntry()) {
- ids.add(next.getResource().getId());
- }
-
- assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2));
-
- // _revinclude's are counted but not _include's
- assertEquals(3, b.getTotal().intValue());
-
- ourLog.info(ids.toString());
}
/**
@@ -603,26 +500,50 @@ public class ResourceProviderDstu2Test {
}
@Test
- public void testCountParam() throws Exception {
- // NB this does not get used- The paging provider has its own limits built in
- ourDaoConfig.setHardSearchLimit(100);
+ public void testEverythingOperation() throws Exception {
+ String methodName = "testEverythingOperation";
- List resources = new ArrayList();
- for (int i = 0; i < 100; i++) {
- Organization org = new Organization();
- org.setName("rpdstu2_testCountParam_01");
- resources.add(org);
+ Organization org1 = new Organization();
+ org1.setName(methodName + "1");
+ IdDt orgId1 = ourClient.create().resource(org1).execute().getId();
+
+ Patient p = new Patient();
+ p.addName().addFamily(methodName);
+ p.getManagingOrganization().setReference(orgId1);
+ IdDt patientId = ourClient.create().resource(p).execute().getId();
+
+ Organization org2 = new Organization();
+ org2.setName(methodName + "1");
+ IdDt orgId2 = ourClient.create().resource(org2).execute().getId();
+
+ Device dev = new Device();
+ dev.setModel(methodName);
+ dev.getOwner().setReference(orgId2);
+ IdDt devId = ourClient.create().resource(dev).execute().getId();
+
+ Observation obs = new Observation();
+ obs.getSubject().setReference(patientId);
+ obs.getDevice().setReference(devId);
+ IdDt obsId = ourClient.create().resource(obs).execute().getId();
+
+ Encounter enc = new Encounter();
+ enc.getPatient().setReference(patientId);
+ IdDt encId = ourClient.create().resource(enc).execute().getId();
+
+ Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
+ ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
+
+ Set ids = new HashSet();
+ for (Entry next : b.getEntry()) {
+ ids.add(next.getResource().getId());
}
- ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
- Bundle found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(10).execute();
- assertEquals(100, found.getTotalResults().getValue().intValue());
- assertEquals(10, found.getEntries().size());
+ assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2));
- found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(999).execute();
- assertEquals(100, found.getTotalResults().getValue().intValue());
- assertEquals(50, found.getEntries().size());
+ // _revinclude's are counted but not _include's
+ assertEquals(3, b.getTotal().intValue());
+ ourLog.info(ids.toString());
}
/**
@@ -644,119 +565,31 @@ public class ResourceProviderDstu2Test {
}
/**
- * See issue #52
+ * Test for issue #60
*/
@Test
- public void testDocumentManifestResources() throws Exception {
- ourFhirCtx.getResourceDefinition(Practitioner.class);
- ourFhirCtx.getResourceDefinition(ca.uhn.fhir.model.dstu.resource.DocumentManifest.class);
+ public void testReadAllInstancesOfType() throws Exception {
+ Patient pat;
- IGenericClient client = ourClient;
+ pat = new Patient();
+ pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_01");
+ ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
- int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
+ pat = new Patient();
+ pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_02");
+ ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
- String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentmanifest.json"));
- client.create().resource(resBody).execute();
-
- int newSize = client.search().forResource(DocumentManifest.class).execute().size();
-
- assertEquals(1, newSize - initialSize);
-
- }
-
- /**
- * See issue #52
- */
- @Test
- public void testDocumentReferenceResources() throws Exception {
- IGenericClient client = ourClient;
-
- int initialSize = client.search().forResource(DocumentReference.class).execute().size();
-
- String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentreference.json"));
- client.create().resource(resBody).execute();
-
- int newSize = client.search().forResource(DocumentReference.class).execute().size();
-
- assertEquals(1, newSize - initialSize);
-
- }
-
- /**
- * See issue #52
- */
- @Test
- public void testDiagnosticOrderResources() throws Exception {
- IGenericClient client = ourClient;
-
- int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size();
-
- DiagnosticOrder res = new DiagnosticOrder();
- res.addIdentifier().setSystem("urn:foo").setValue("123");
-
- client.create().resource(res).execute();
-
- int newSize = client.search().forResource(DiagnosticOrder.class).execute().size();
-
- assertEquals(1, newSize - initialSize);
-
- }
-
- private void delete(String theResourceType, String theParamName, String theParamValue) {
- Bundle resources = ourClient.search().forResource(theResourceType).where(new StringClientParam(theParamName).matches().value(theParamValue)).execute();
- for (IResource next : resources.toListOfResources()) {
- ourLog.info("Deleting resource: {}", next.getId());
- ourClient.delete().resource(next).execute();
+ {
+ Bundle returned = ourClient.search().forResource(Patient.class).encodedXml().execute();
+ assertThat(returned.size(), greaterThan(1));
+ assertEquals(BundleTypeEnum.SEARCHSET, returned.getType().getValueAsEnum());
}
- }
-
- private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue) {
- Bundle resources = ourClient.search().forResource(theResourceType).where(new TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
- for (IResource next : resources.toListOfResources()) {
- ourLog.info("Deleting resource: {}", next.getId());
- ourClient.delete().resource(next).execute();
+ {
+ Bundle returned = ourClient.search().forResource(Patient.class).encodedJson().execute();
+ assertThat(returned.size(), greaterThan(1));
}
}
- @Test
- public void testDeepChaining() {
- delete("Location", Location.SP_NAME, "testDeepChainingL1");
- delete("Location", Location.SP_NAME, "testDeepChainingL2");
- deleteToken("Encounter", Encounter.SP_IDENTIFIER, "urn:foo", "testDeepChainingE1");
-
- Location l1 = new Location();
- l1.getNameElement().setValue("testDeepChainingL1");
- IdDt l1id = ourClient.create().resource(l1).execute().getId();
-
- Location l2 = new Location();
- l2.getNameElement().setValue("testDeepChainingL2");
- l2.getPartOf().setReference(l1id.toVersionless().toUnqualified());
- IdDt l2id = ourClient.create().resource(l2).execute().getId();
-
- Encounter e1 = new Encounter();
- e1.addIdentifier().setSystem("urn:foo").setValue("testDeepChainingE1");
- e1.getStatusElement().setValueAsEnum(EncounterStateEnum.IN_PROGRESS);
- e1.getClassElementElement().setValueAsEnum(EncounterClassEnum.HOME);
- ca.uhn.fhir.model.dstu2.resource.Encounter.Location location = e1.addLocation();
- location.getLocation().setReference(l2id.toUnqualifiedVersionless());
- location.setPeriod(new PeriodDt().setStartWithSecondsPrecision(new Date()).setEndWithSecondsPrecision(new Date()));
- IdDt e1id = ourClient.create().resource(e1).execute().getId();
-
- //@formatter:off
- Bundle res = ourClient.search()
- .forResource(Encounter.class)
- .where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1"))
- .include(Encounter.INCLUDE_LOCATION)
- .include(Location.INCLUDE_PARTOF)
- .execute();
- //@formatter:on
-
- assertEquals(3, res.size());
- assertEquals(1, res.getResources(Encounter.class).size());
- assertEquals(e1id.toUnqualifiedVersionless(), res.getResources(Encounter.class).get(0).getId().toUnqualifiedVersionless());
-
- }
-
@Test
public void testSaveAndRetrieveExistingNarrative() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSaveAndRetrieveExistingNarrative01");
@@ -804,6 +637,20 @@ public class ResourceProviderDstu2Test {
assertThat(actual.getText().getDiv().getValueAsString(), containsString("Identifier testSearchByResourceChain01 "));
}
+ @Test
+ public void testSearchBundleDoesntIncludeTextElement() throws Exception {
+ HttpGet read = new HttpGet(ourServerBase + "/Patient?_format=json");
+ CloseableHttpResponse response = ourHttpClient.execute(read);
+ try {
+ String text = IOUtils.toString(response.getEntity().getContent());
+ ourLog.info(text);
+ assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatusLine().getStatusCode());
+ assertThat(text, not(containsString("\"text\",\"type\"")));
+ } finally {
+ response.close();
+ }
+ }
+
@Test
public void testSearchByIdentifier() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSearchByIdentifier01");
@@ -874,6 +721,118 @@ public class ResourceProviderDstu2Test {
}
+ @Test
+ public void testSearchWithInclude() throws Exception {
+ Organization org = new Organization();
+ org.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude01");
+ IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
+
+ Patient pat = new Patient();
+ pat.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude02");
+ pat.getManagingOrganization().setReference(orgId);
+ ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
+
+ //@formatter:off
+ Bundle found = ourClient
+ .search()
+ .forResource(Patient.class)
+ .where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system:rpdstu2","testSearchWithInclude02"))
+ .include(Patient.INCLUDE_ORGANIZATION)
+ .prettyPrint()
+ .execute();
+ //@formatter:on
+
+ assertEquals(2, found.size());
+ assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
+ assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum());
+ assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
+ assertThat(found.getEntries().get(0).getResource().getText().getDiv().getValueAsString(), containsString(" resources = new ArrayList();
+ for (int i = 0; i < 20; i++) {
+ Organization org = new Organization();
+ org.setName(methodName + "_0" + i);
+ resources.add(org);
+ }
+ ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
+
+ Organization org = new Organization();
+ org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
+ org.setName(methodName + "name");
+ IdDt orgNotMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
+
+ org = new Organization();
+ org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
+ IdDt orgMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
+
+ {
+ //@formatter:off
+ Bundle found = ourClient
+ .search()
+ .forResource(Organization.class)
+ .where(Organization.NAME.isMissing(false))
+ .limitTo(100)
+ .prettyPrint()
+ .execute();
+ //@formatter:on
+
+ List list = toIdListUnqualifiedVersionless(found);
+ ourLog.info(methodName + ": " + list.toString());
+ assertThat("Wanted " + orgNotMissing + " but got: " + list, list, containsInRelativeOrder(orgNotMissing));
+ assertThat(list, not(containsInRelativeOrder(orgMissing)));
+ }
+
+ //@formatter:off
+ Bundle found = ourClient
+ .search()
+ .forResource(Organization.class)
+ .where(Organization.NAME.isMissing(true))
+ .limitTo(100)
+ .prettyPrint()
+ .execute();
+ //@formatter:on
+
+ List list = toIdListUnqualifiedVersionless(found);
+ ourLog.info(methodName + " found: " + list.toString() + " - Wanted " + orgMissing + " but not " + orgNotMissing);
+ assertThat(list, not(containsInRelativeOrder(orgNotMissing)));
+ assertThat("Wanted " + orgMissing + " but found: " + list, list, containsInRelativeOrder(orgMissing));
+ }
+
+ /**
+ * Test for issue #60
+ */
+ @Test
+ public void testStoreUtf8Characters() throws Exception {
+ Organization org = new Organization();
+ org.setName("測試醫院");
+ org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
+ IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
+
+ // Read back directly from the DAO
+ {
+ Organization returned = ourOrganizationDao.read(orgId);
+ String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
+ ourLog.info(val);
+ assertThat(val, containsString(""));
+ }
+ // Read back through the HTTP API
+ {
+ Organization returned = ourClient.read(Organization.class, orgId);
+ String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
+ ourLog.info(val);
+ assertThat(val, containsString(""));
+ }
+ }
+
@Test
public void testTryToCreateResourceWithReferenceThatDoesntExist() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testTryToCreateResourceWithReferenceThatDoesntExist01");
@@ -919,6 +878,41 @@ public class ResourceProviderDstu2Test {
}
+ @Test
+ public void testUpdateResourceConditional() throws IOException {
+ String methodName = "testUpdateResourceConditional";
+
+ Patient pt = new Patient();
+ pt.addName().addFamily(methodName);
+ String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
+
+ HttpPost post = new HttpPost(ourServerBase + "/Patient?name=" + methodName);
+ post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
+ CloseableHttpResponse response = ourHttpClient.execute(post);
+ IdDt id;
+ try {
+ assertEquals(201, response.getStatusLine().getStatusCode());
+ String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
+ assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
+ id = new IdDt(newIdString);
+ } finally {
+ response.close();
+ }
+
+ HttpPut put = new HttpPut(ourServerBase + "/Patient?name=" + methodName);
+ put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
+ response = ourHttpClient.execute(put);
+ try {
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ IdDt newId = new IdDt(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue());
+ assertEquals(id.toVersionless(), newId.toVersionless()); // version shouldn't match for conditional update
+ assertNotEquals(id, newId);
+ } finally {
+ response.close();
+ }
+
+ }
+
@Test
public void testUpdateWithClientSuppliedIdWhichDoesntExist() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2");
@@ -937,6 +931,68 @@ public class ResourceProviderDstu2Test {
}
+ @Test
+ public void testValidateResource() throws IOException {
+
+ Patient patient = new Patient();
+ patient.addName().addGiven("James");
+ patient.setBirthDate(new DateDt("2011-02-02"));
+
+ Parameters input = new Parameters();
+ input.addParameter().setName("resource").setResource(patient);
+
+ String inputStr = ourFhirCtx.newXmlParser().encodeResourceToString(input);
+ ourLog.info(inputStr);
+
+ HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
+ post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
+
+ CloseableHttpResponse response = ourHttpClient.execute(post);
+ try {
+ String resp = IOUtils.toString(response.getEntity().getContent());
+ ourLog.info(resp);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ } finally {
+ IOUtils.closeQuietly(response.getEntity().getContent());
+ response.close();
+ }
+ }
+
+// @Test
+ public void testValidateResourceHuge() throws IOException {
+
+ Patient patient = new Patient();
+ patient.addName().addGiven("James" + StringUtils.leftPad("James", 1000000, 'A'));;
+ patient.setBirthDate(new DateDt("2011-02-02"));
+
+ Parameters input = new Parameters();
+ input.addParameter().setName("resource").setResource(patient);
+
+ String inputStr = ourFhirCtx.newXmlParser().encodeResourceToString(input);
+ ourLog.info(inputStr);
+
+ HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
+ post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
+
+ CloseableHttpResponse response = ourHttpClient.execute(post);
+ try {
+ String resp = IOUtils.toString(response.getEntity().getContent());
+ ourLog.info(resp);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ } finally {
+ IOUtils.closeQuietly(response.getEntity().getContent());
+ response.close();
+ }
+ }
+
+ private List toIdListUnqualifiedVersionless(Bundle found) {
+ List list = new ArrayList();
+ for (BundleEntry next : found.getEntries()) {
+ list.add(next.getResource().getId().toUnqualifiedVersionless());
+ }
+ return list;
+ }
+
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
index 0cb6487cd33..6759d9856aa 100644
--- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
+++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
@@ -135,7 +135,7 @@ public class TestRestfulServer extends RestfulServer {
registerInterceptor(new ResponseHighlighterInterceptor());
/*
- * Default to XML and pretty printing
+ * Default to JSON with pretty printing
*/
setDefaultPrettyPrint(true);
setDefaultResponseEncoding(EncodingEnum.JSON);
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/rp/FhirtestBaseResourceProviderDstu2.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/rp/FhirtestBaseResourceProviderDstu2.java
new file mode 100644
index 00000000000..1a1055163d0
--- /dev/null
+++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/rp/FhirtestBaseResourceProviderDstu2.java
@@ -0,0 +1,8 @@
+package ca.uhn.fhirtest.rp;
+
+import ca.uhn.fhir.jpa.provider.JpaResourceProviderDstu2;
+import ca.uhn.fhir.model.api.IResource;
+
+public class FhirtestBaseResourceProviderDstu2 extends JpaResourceProviderDstu2 {
+
+}
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/webapp/WEB-INF/hapi-fhir-server-config.xml b/hapi-fhir-jpaserver-uhnfhirtest/src/main/webapp/WEB-INF/hapi-fhir-server-config.xml
index 45432d2ab5c..ee0c94799e4 100644
--- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/webapp/WEB-INF/hapi-fhir-server-config.xml
+++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/webapp/WEB-INF/hapi-fhir-server-config.xml
@@ -32,7 +32,7 @@
+ value="Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"/>
\ No newline at end of file
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 47d1060ebcc..08d4c6ad240 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
@@ -36,6 +36,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
import ca.uhn.fhir.model.dstu.composite.AddressDt;
+import ca.uhn.fhir.model.dstu.composite.AttachmentDt;
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
@@ -116,6 +117,30 @@ public class XmlParserTest {
assertEquals("OrgName", ((MyOrganization) parse.getSomeOrganization().getResource()).getName().getValue());
}
+
+// @Test
+ public void testParseAndEncodeHugeValue() {
+ int len = 1000000;
+ byte[] bytes = new byte[len];
+ for (int i = 0; i < len; i++) {
+ bytes[i] = (byte) (Math.random() * Byte.MAX_VALUE);
+ }
+
+ AttachmentDt att = new AttachmentDt();
+ att.setData(bytes);
+
+ Observation obs = new Observation();
+ obs.setValue(att);
+
+ String str = ourCtx.newXmlParser().encodeResourceToString(obs);
+ assertThat(str.length(), Matchers.greaterThan(len));
+
+ obs = ourCtx.newXmlParser().parseResource(Observation.class, str);
+ att = (AttachmentDt) obs.getValue();
+ assertEquals(bytes, att.getData().getValue());
+ }
+
+
/**
* 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/server/ResourceMethodTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ResourceMethodTest.java
index 6d618d7b87b..9376769a601 100644
--- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ResourceMethodTest.java
+++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ResourceMethodTest.java
@@ -1,6 +1,7 @@
package ca.uhn.fhir.rest.server;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.HashSet;
@@ -16,7 +17,7 @@ import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.method.IParameter;
-import ca.uhn.fhir.rest.method.Request;
+import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.method.SearchMethodBinding;
import ca.uhn.fhir.rest.method.SearchParameter;
@@ -48,7 +49,7 @@ public class ResourceMethodTest {
inputParams.add("firstName");
inputParams.add("lastName");
- assertEquals(false, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
+ assertEquals(false, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
}
@Test
@@ -63,7 +64,7 @@ public class ResourceMethodTest {
Set inputParams = new HashSet();
inputParams.add("mrn");
- assertEquals(true, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
+ assertEquals(true, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
}
@Test
@@ -80,7 +81,7 @@ public class ResourceMethodTest {
inputParams.add("firstName");
inputParams.add("mrn");
- assertEquals(true, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
+ assertEquals(true, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
}
@Test
@@ -98,7 +99,7 @@ public class ResourceMethodTest {
inputParams.add("lastName");
inputParams.add("mrn");
- Request params = Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams);
+ RequestDetails params = RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams);
boolean actual = rm.incomingServerRequestMatchesMethod(params);
assertTrue( actual); // True
}
@@ -119,6 +120,6 @@ public class ResourceMethodTest {
inputParams.add("mrn");
inputParams.add("foo");
- assertEquals(false, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
+ assertEquals(false, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
}
}
diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ValidateTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu1Test.java
similarity index 98%
rename from hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ValidateTest.java
rename to hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu1Test.java
index 30e98522a33..b9a2c531362 100644
--- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ValidateTest.java
+++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu1Test.java
@@ -35,11 +35,11 @@ import ca.uhn.fhir.util.PortUtil;
/**
* Created by dsotnikov on 2/25/2014.
*/
-public class ValidateTest {
+public class ValidateDstu1Test {
private static CloseableHttpClient ourClient;
private static EncodingEnum ourLastEncoding;
private static String ourLastResourceBody;
- private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateTest.class);
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateDstu1Test.class);
private static int ourPort;
private static Server ourServer;
diff --git a/hapi-fhir-structures-dstu2/.gitignore b/hapi-fhir-structures-dstu2/.gitignore
index bc93860f21e..be015a3d566 100644
--- a/hapi-fhir-structures-dstu2/.gitignore
+++ b/hapi-fhir-structures-dstu2/.gitignore
@@ -141,3 +141,4 @@ local.properties
/target/
/target/
/target/
+/target/
diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu2Test.java
new file mode 100644
index 00000000000..1b2fc6e53ae
--- /dev/null
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu2Test.java
@@ -0,0 +1,225 @@
+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.concurrent.TimeUnit;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+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.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.IResource;
+import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
+import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
+import ca.uhn.fhir.model.dstu2.resource.Organization;
+import ca.uhn.fhir.model.dstu2.resource.Parameters;
+import ca.uhn.fhir.model.dstu2.resource.Patient;
+import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.model.primitive.StringDt;
+import ca.uhn.fhir.rest.annotation.ResourceParam;
+import ca.uhn.fhir.rest.annotation.Validate;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.ValidationModeEnum;
+import ca.uhn.fhir.util.PortUtil;
+
+/**
+ * Created by dsotnikov on 2/25/2014.
+ */
+public class ValidateDstu2Test {
+ private static CloseableHttpClient ourClient;
+ private static EncodingEnum ourLastEncoding;
+ private static String ourLastResourceBody;
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateDstu2Test.class);
+ private static int ourPort;
+ private static Server ourServer;
+ private static BaseOperationOutcome ourOutcomeToReturn;
+ private static ValidationModeEnum ourLastMode;
+ private static String ourLastProfile;
+
+ @Before()
+ public void before() {
+ ourLastResourceBody = null;
+ ourLastEncoding = null;
+ ourOutcomeToReturn = null;
+ ourLastMode = null;
+ ourLastProfile = null;
+ }
+
+ @Test
+ public void testValidateWithOptions() throws Exception {
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setValue("001");
+ patient.addIdentifier().setValue("002");
+
+ Parameters params = new Parameters();
+ params.addParameter().setName("resource").setResource(patient);
+ params.addParameter().setName("profile").setValue(new StringDt("http://foo"));
+ params.addParameter().setName("mode").setValue(new StringDt(ValidationModeEnum.CREATE.name()));
+
+ HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$validate");
+ httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(params), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
+
+ HttpResponse status = ourClient.execute(httpPost);
+ String resp = IOUtils.toString(status.getEntity().getContent());
+ IOUtils.closeQuietly(status.getEntity().getContent());
+
+ assertEquals(200, status.getStatusLine().getStatusCode());
+
+ assertThat(resp, stringContainsInOrder(" getResourceType() {
+ return Patient.class;
+ }
+
+ }
+
+ public static class OrganizationProvider implements IResourceProvider {
+
+ @Validate()
+ public MethodOutcome validate(@ResourceParam String theResourceBody, @ResourceParam EncodingEnum theEncoding) {
+ ourLastResourceBody = theResourceBody;
+ ourLastEncoding = theEncoding;
+
+ return new MethodOutcome(new IdDt("001"));
+ }
+
+ @Override
+ public Class extends IResource> getResourceType() {
+ return Organization.class;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorTest.java
similarity index 60%
rename from hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorTest.java
rename to hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorTest.java
index e9d63086887..3407a78a722 100644
--- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorTest.java
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorTest.java
@@ -1,7 +1,9 @@
package ca.uhn.fhir.rest.server.interceptor;
import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import java.util.Collections;
import java.util.HashMap;
@@ -26,13 +28,18 @@ import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.slf4j.Logger;
-import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
-import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
-import ca.uhn.fhir.model.dstu.resource.Patient;
-import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
+import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
+import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
+import ca.uhn.fhir.model.dstu2.resource.Bundle;
+import ca.uhn.fhir.model.dstu2.resource.Patient;
+import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
+import ca.uhn.fhir.model.dstu2.valueset.IdentifierUseEnum;
+import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.annotation.IdParam;
+import ca.uhn.fhir.rest.annotation.Operation;
+import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
@@ -51,17 +58,15 @@ public class LoggingInterceptorTest {
private static RestfulServer servlet;
private IServerInterceptor myInterceptor;
-
-
@Test
public void testRead() throws Exception {
-
+
LoggingInterceptor interceptor = new LoggingInterceptor();
- servlet.setInterceptors(Collections.singletonList((IServerInterceptor)interceptor));
-
+ servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
+
Logger logger = mock(Logger.class);
interceptor.setLogger(logger);
-
+
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
@@ -73,14 +78,14 @@ public class LoggingInterceptorTest {
@Test
public void testSearch() throws Exception {
-
+
LoggingInterceptor interceptor = new LoggingInterceptor();
- interceptor.setMessageFormat( "${operationType} - ${idOrResourceName} - ${requestParameters}");
- servlet.setInterceptors(Collections.singletonList((IServerInterceptor)interceptor));
-
+ interceptor.setMessageFormat("${operationType} - ${idOrResourceName} - ${requestParameters}");
+ servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
+
Logger logger = mock(Logger.class);
interceptor.setLogger(logger);
-
+
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_id=1");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
@@ -89,16 +94,16 @@ public class LoggingInterceptorTest {
verify(logger, times(1)).info(captor.capture());
assertThat(captor.getValue(), StringContains.containsString("search-type - Patient - ?_id=1"));
}
-
+
@Test
public void testMetadata() throws Exception {
-
+
LoggingInterceptor interceptor = new LoggingInterceptor();
- servlet.setInterceptors(Collections.singletonList((IServerInterceptor)interceptor));
-
+ servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
+
Logger logger = mock(Logger.class);
interceptor.setLogger(logger);
-
+
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/metadata");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
@@ -108,8 +113,63 @@ public class LoggingInterceptorTest {
assertThat(captor.getValue(), StringContains.containsString("metadata - "));
}
-
-
+ @Test
+ public void testOperationOnInstance() throws Exception {
+
+ LoggingInterceptor interceptor = new LoggingInterceptor();
+ interceptor.setMessageFormat("${operationType} - ${operationName} - ${idOrResourceName}");
+ servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
+
+ Logger logger = mock(Logger.class);
+ interceptor.setLogger(logger);
+
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$everything");
+ HttpResponse status = ourClient.execute(httpGet);
+ IOUtils.closeQuietly(status.getEntity().getContent());
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
+ verify(logger, times(1)).info(captor.capture());
+ assertEquals("extended-operation-instance - $everything - Patient/123", captor.getValue());
+ }
+
+ @Test
+ public void testOperationOnServer() throws Exception {
+
+ LoggingInterceptor interceptor = new LoggingInterceptor();
+ interceptor.setMessageFormat("${operationType} - ${operationName} - ${idOrResourceName}");
+ servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
+
+ Logger logger = mock(Logger.class);
+ interceptor.setLogger(logger);
+
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$everything");
+ HttpResponse status = ourClient.execute(httpGet);
+ IOUtils.closeQuietly(status.getEntity().getContent());
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
+ verify(logger, times(1)).info(captor.capture());
+ assertEquals("extended-operation-server - $everything - ", captor.getValue());
+ }
+
+ @Test
+ public void testOperationOnType() throws Exception {
+
+ LoggingInterceptor interceptor = new LoggingInterceptor();
+ interceptor.setMessageFormat("${operationType} - ${operationName} - ${idOrResourceName}");
+ servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
+
+ Logger logger = mock(Logger.class);
+ interceptor.setLogger(logger);
+
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$everything");
+ HttpResponse status = ourClient.execute(httpGet);
+ IOUtils.closeQuietly(status.getEntity().getContent());
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
+ verify(logger, times(1)).info(captor.capture());
+ assertEquals("extended-operation-type - $everything - Patient", captor.getValue());
+ }
+
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
@@ -121,17 +181,17 @@ public class LoggingInterceptorTest {
servlet.setInterceptors(Collections.singletonList(myInterceptor));
}
-
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);
- DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
-
ServletHandler proxyHandler = new ServletHandler();
servlet = new RestfulServer();
- servlet.setResourceProviders(patientProvider);
+
+ servlet.setResourceProviders(new DummyPatientResourceProvider());
+ servlet.setPlainProviders(new PlainProvider());
+
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
ourServer.setHandler(proxyHandler);
@@ -164,7 +224,7 @@ public class LoggingInterceptorTest {
patient.getName().add(new HumanNameDt());
patient.getName().get(0).addFamily("Test");
patient.getName().get(0).addGiven("PatientTwo");
- patient.getGender().setText("F");
+ patient.setGender(AdministrativeGenderEnum.FEMALE);
patient.getId().setValue("2");
idToPatient.put("2", patient);
}
@@ -185,7 +245,6 @@ public class LoggingInterceptorTest {
return retVal;
}
-
/**
* Retrieve the resource by its identifier
*
@@ -203,12 +262,27 @@ public class LoggingInterceptorTest {
}
}
-
@Override
public Class getResourceType() {
return Patient.class;
}
+ @Operation(name = "$everything", idempotent = true)
+ public Bundle patientTypeOperation(@IdParam IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
+
+ Bundle retVal = new Bundle();
+ // Populate bundle with matching resources
+ return retVal;
+ }
+
+ @Operation(name = "$everything", idempotent = true)
+ public Bundle patientTypeOperation(@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
+
+ Bundle retVal = new Bundle();
+ // Populate bundle with matching resources
+ return retVal;
+ }
+
private Patient createPatient1() {
Patient patient = new Patient();
patient.addIdentifier();
@@ -218,11 +292,23 @@ public class LoggingInterceptorTest {
patient.addName();
patient.getName().get(0).addFamily("Test");
patient.getName().get(0).addGiven("PatientOne");
- patient.getGender().setText("M");
+ patient.setGender(AdministrativeGenderEnum.MALE);
patient.getId().setValue("1");
return patient;
}
}
+ public static class PlainProvider {
+
+ @Operation(name = "$everything", idempotent = true)
+ public Bundle patientTypeOperation(@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
+
+ Bundle retVal = new Bundle();
+ // Populate bundle with matching resources
+ return retVal;
+ }
+
+ }
+
}
diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml
index 0e02476c308..915e44721f0 100644
--- a/hapi-fhir-structures-hl7org-dstu2/pom.xml
+++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml
@@ -191,17 +191,36 @@
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+ public
+
+
+
+
+
org.codehaus.mojo
license-maven-plugin
- ${maven_license_plugin_version}
true
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ true
+ true
+
+
diff --git a/hapi-fhir-structures-hl7org-dstu2/tmp.txt b/hapi-fhir-structures-hl7org-dstu2/tmp.txt
new file mode 100644
index 00000000000..76cff850b0b
--- /dev/null
+++ b/hapi-fhir-structures-hl7org-dstu2/tmp.txt
@@ -0,0 +1 @@
+javac -d /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/target/classes -classpath /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/target/classes:/Users/t3903uhn/.m2/repository/ca/uhn/hapi/fhir/hapi-fhir-base/1.1-SNAPSHOT/hapi-fhir-base-1.1-SNAPSHOT.jar:/Users/t3903uhn/.m2/repository/javax/json/javax.json-api/1.0/javax.json-api-1.0.jar:/Users/t3903uhn/.m2/repository/org/glassfish/javax.json/1.0.4/javax.json-1.0.4.jar:/Users/t3903uhn/.m2/repository/org/codehaus/woodstox/woodstox-core-asl/4.4.1/woodstox-core-asl-4.4.1.jar:/Users/t3903uhn/.m2/repository/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar:/Users/t3903uhn/.m2/repository/org/codehaus/woodstox/stax2-api/3.1.4/stax2-api-3.1.4.jar:/Users/t3903uhn/.m2/repository/org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar:/Users/t3903uhn/.m2/repository/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/Users/t3903uhn/.m2/repository/commons-io/commons-io/2.4/commons-io-2.4.jar:/Users/t3903uhn/.m2/repository/org/slf4j/slf4j-api/1.7.10/slf4j-api-1.7.10.jar:/Users/t3903uhn/.m2/repository/org/slf4j/jcl-over-slf4j/1.7.10/jcl-over-slf4j-1.7.10.jar:/Users/t3903uhn/.m2/repository/org/apache/httpcomponents/httpclient/4.4/httpclient-4.4.jar:/Users/t3903uhn/.m2/repository/org/apache/httpcomponents/httpcore/4.4/httpcore-4.4.jar:/Users/t3903uhn/.m2/repository/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar:/Users/t3903uhn/.m2/repository/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar:/Users/t3903uhn/.m2/repository/net/sf/saxon/Saxon-HE/9.6.0-4/Saxon-HE-9.6.0-4.jar:/Users/t3903uhn/.m2/repository/com/google/code/gson/gson/2.3.1/gson-2.3.1.jar: -sourcepath /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java:/Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/target/generated-sources/annotations: /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/CodeType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Encounter.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DomainResource.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Timing.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/PaymentNotice.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/annotations/Block.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Condition.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/ZipURIResolver.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/validation/XmlLocationData.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Device.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Contraindication.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Provenance.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/TemporalPrecisionEnum.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/terminologies/ValueSetExpander.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Procedure.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/InstantType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Group.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/OperationDefinition.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DateType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BaseNarrative.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/OrderResponse.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/StringType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/EligibilityResponse.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/CodeableConcept.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BaseResource.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/validation/InstanceValidator.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Location.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/utils/ProfileUtilities.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/List_.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/UuidType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/validation/ProfileValidator.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DocumentReference.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ConceptMap.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Property.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Enumerations.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DataElement.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/EnrollmentResponse.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Organization.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/annotations/Description.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/AuditEvent.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DateTimeType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/VisionPrescription.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Composition.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/OidType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Contract.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/validation/IResourceValidator.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/UriType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/PrimitiveType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Enumeration.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/utils/ToolingExtensions.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ClaimResponse.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Flag.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Money.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ExplanationOfBenefit.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/validation/ValidationMessage.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/AllergyIntolerance.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Schedule.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Appointment.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DecimalType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/terminologies/ValueSetExpanderFactory.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Identifier.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Factory.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ImagingStudy.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Immunization.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ExtensionHelper.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/RelatedPerson.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/ca/uhn/fhir/validation/StructureDefinitionValidator.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Distance.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Age.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DeviceComponent.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/IntegerType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/xml/IXMLWriter.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerProfileProvider.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Questionnaire.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Coding.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/UnsignedIntType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/SupplyDelivery.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/IdType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/SidType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/FamilyMemberHistory.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DeviceUseStatement.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BaseReference.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ProcessResponse.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/TestScript.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/HumanName.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Medication.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Specimen.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/SampledData.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/annotations/Extension.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/xhtml/NodeType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/client/IFHIRClient.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/CommaSeparatedStringBuilder.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlComposer.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Basic.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ImmunizationRecommendation.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlParser.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BaseExtension.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/annotations/DatatypeDef.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/validation/BaseValidator.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Slot.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ResourceType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/CSFileInputStream.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BooleanType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Signature.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Supply.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ProcedureRequest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/terminologies/ValueSetExpansionCache.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/MedicationStatement.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/PositiveIntType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/MedicationDispense.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Configuration.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ReferralRequest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ContactPoint.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Practitioner.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/annotations/Child.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/terminologies/ValueSetChecker.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BaseBinary.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/FileNotifier.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DeviceUseRequest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Type.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ValueSet.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Media.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/annotations/ResourceDef.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/EpisodeOfCare.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ClinicalImpression.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Binary.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Attachment.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/xhtml/HeirarchicalTableGenerator.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/PaymentReconciliation.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BackboneElement.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DocumentManifest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/HealthcareService.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Comparison.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/client/ResourceFormat.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/xml/XMLUtil.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DeviceMetric.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BaseDateTimeType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Patient.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/NamingSystem.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlDocument.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/StructureDefinition.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/EligibilityRequest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Goal.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/Utilities.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/TextStreamWriter.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/CommunicationRequest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/client/FeedFormat.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/CSFile.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ElementDefinition.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Communication.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Conformance.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Period.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/Inflector.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2hl7org/Dstu2Hl7OrgBundleFactory.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/BodySite.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/FhirEnum.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DateAndTime.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/formats/FormatUtilities.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Subscription.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Observation.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Parameters.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Coverage.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Claim.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/MedicationPrescription.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DiagnosticReport.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/OperationOutcome.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Person.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Reference.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/EnumFactory.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Ratio.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/NutritionOrder.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/MyURIResolver.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Duration.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Narrative.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/utils/WorkerContext.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Extension.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/SearchParameter.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/TimeType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/annotations/SearchParamDefinition.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/terminologies/ITerminologyServices.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Base.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/QuestionnaireAnswers.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Quantity.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ResourceFactory.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Constants.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ImagingObjectSelection.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ProcessRequest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/RiskAssessment.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/ResourceEnumerations.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/SupplyRequest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Range.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/FhirDstu2Hl7Org.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Base64BinaryType.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/CarePlan.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/AppointmentResponse.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Resource.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/MedicationAdministration.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Address.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Order.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/MessageHeader.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/EnrollmentRequest.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Count.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/DiagnosticOrder.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Element.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Substance.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Meta.java /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/Bundle.java -s /Users/t3903uhn/git/hapi-fhir/hapi-fhir-structures-hl7org-dstu2/target/generated-sources/annotations -g -nowarn -target 1.6 -source 1.6 -encoding UTF-8
diff --git a/pom.xml b/pom.xml
index ecae7a34614..87cb23576e1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -230,8 +230,8 @@
1.6
1.6
- javac-with-errorprone
- true
+
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index be1be038635..4352727bc74 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -55,6 +55,9 @@
Web tester UI now supports _revinclude
+
+ LoggingInterceptor for server now supports logging DSTU2 extended operations by name
+
diff --git a/src/site/xdoc/doc_rest_operations.xml b/src/site/xdoc/doc_rest_operations.xml
index c65e9b1e070..129c7ae8632 100644
--- a/src/site/xdoc/doc_rest_operations.xml
+++ b/src/site/xdoc/doc_rest_operations.xml
@@ -1059,6 +1059,17 @@
operation tests whether a resource passes business validation, and would be
acceptable for saving to a server (e.g. by a create or update method).
+
+ Note on FHIR versions:
+ In FHIR DSTU1 the validate operation used a URL resembling http://example.com/Patient/_validate
+ with a resource in the HTTP POST body. In FHIR DSTU2, validate has been changed to use the
+ extended operation mechanism. It now uses a URL
+ resembling http://example.com/Patient/$validate
and takes a
+ Parameters resource as input in the method body.
+ The mechanism described below may be used for both DSTU1 and DSTU2+ servers, and HAPI
+ will automatically use the correct form depending on what FHIR version the
+ server is configured to use.
+
Validate methods must be annotated with the
@Validate
@@ -1107,11 +1118,20 @@
+
+ In the example above, only the @ResourceParam
parameter is technically required, but
+ in DSTU2 you are encouraged to also add the following parameters:
+
+
+ @Validate.Mode ValidationModeEnum mode - This is the validation mode (see the FHIR specification for information on this)
+ @Validate.Profile String profile - This is the profile to validate against (see the FHIR specification for more information on this)
+
+
Example URL to invoke this method (this would be invoked using an HTTP POST,
- with the resource in the POST body):
+ with a Parameters resource in the POST body):
- http://fhir.example.com/Patient/_validate
+ http://fhir.example.com/Patient/$validate
@@ -1508,6 +1528,7 @@
http://fhir.example.com/Patient/123/Condition
+