Add operation blocking interceptor (#4057)
* Add operation blocking interceptor * Work on interceptor * Work on interceptor * FIx up docs * Address CVE * Tweak changelog * Address review comments
This commit is contained in:
parent
2770295638
commit
3935b78083
|
@ -364,6 +364,26 @@ public enum Pointcut implements IPointcut {
|
||||||
"ca.uhn.fhir.rest.server.interceptor.IServerInterceptor$ActionRequestDetails"
|
"ca.uhn.fhir.rest.server.interceptor.IServerInterceptor$ActionRequestDetails"
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b>Server Hook:</b>
|
||||||
|
* This method is called when a resource provider method is registered and being bound
|
||||||
|
* by the HAPI FHIR Plain Server / RestfulServer.
|
||||||
|
* <p>
|
||||||
|
* Hooks may accept the following parameters:
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* ca.uhn.fhir.rest.server.method.BaseMethodBinding - The method binding.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* Hook methods may modify the method binding, replace it, or return <code>null</code> to cancel the binding.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
SERVER_PROVIDER_METHOD_BOUND("ca.uhn.fhir.rest.server.method.BaseMethodBinding",
|
||||||
|
"ca.uhn.fhir.rest.server.method.BaseMethodBinding"),
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>Server Hook:</b>
|
* <b>Server Hook:</b>
|
||||||
* This method is called upon any exception being thrown within the server's request processing code. This includes
|
* This method is called upon any exception being thrown within the server's request processing code. This includes
|
||||||
|
|
|
@ -191,7 +191,7 @@ public enum RestOperationTypeEnum {
|
||||||
/**
|
/**
|
||||||
* Returns the enumerated value associated with this code
|
* Returns the enumerated value associated with this code
|
||||||
*/
|
*/
|
||||||
public RestOperationTypeEnum forCode(@Nonnull String theCode) {
|
public static RestOperationTypeEnum forCode(@Nonnull String theCode) {
|
||||||
Validate.notNull(theCode, "theCode must not be null");
|
Validate.notNull(theCode, "theCode must not be null");
|
||||||
return CODE_TO_ENUM.get(theCode);
|
return CODE_TO_ENUM.get(theCode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 4057
|
||||||
|
title: "A new built-in server interceptor called the InteractionBlockingInterceptor has been added. This interceptor
|
||||||
|
allows individual operations to be included/excluded from a RestfulServer's exported capabilities."
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 4057
|
||||||
|
title: "The OpenApi generator now allows additional CSS customization for the Swagger UI page, as well as the
|
||||||
|
option to disable resource type pages."
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
- item:
|
||||||
|
type: "add"
|
||||||
|
title: "The version of a few dependencies have been bumped to the latest versions
|
||||||
|
(dependent HAPI modules listed in brackets):
|
||||||
|
<ul>
|
||||||
|
<li>Woodstox (Base): 6.2.5 -> 6.3.1</li>
|
||||||
|
</ul>
|
||||||
|
"
|
||||||
|
|
|
@ -201,6 +201,15 @@ Some security audit tools require that servers return an HTTP 405 if an unsuppor
|
||||||
An interceptor can be registered against your server that enables support for OpenAPI (aka Swagger) automatically. See [OpenAPI](/docs/server_plain/openapi.html) for more information.
|
An interceptor can be registered against your server that enables support for OpenAPI (aka Swagger) automatically. See [OpenAPI](/docs/server_plain/openapi.html) for more information.
|
||||||
|
|
||||||
|
|
||||||
|
# Server: Interaction Blocking
|
||||||
|
|
||||||
|
The interaction blocking interceptor selectively disables specific interactions that are provided in registered resource providers.
|
||||||
|
|
||||||
|
* [InteractionBlockingInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/InteractionBlockingInterceptor.html)
|
||||||
|
* [InteractionBlockingInterceptor Source](https://github.com/hapifhir/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/InteractionBlockingInterceptor.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Subscription: Subscription Debug Log Interceptor
|
# Subscription: Subscription Debug Log Interceptor
|
||||||
|
|
||||||
When using Subscriptions, the debug log interceptor can be used to add a number of additional lines to the server logs showing the internals of the subscription processing pipeline.
|
When using Subscriptions, the debug log interceptor can be used to add a number of additional lines to the server logs showing the internals of the subscription processing pipeline.
|
||||||
|
|
|
@ -45,9 +45,9 @@ The server will produce a response resembling the following:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Diff Instance
|
# Diff Server
|
||||||
|
|
||||||
When the $diff operation is invoked at the instance level (meaning it is invoked on a specific resource ID), it will compare two versions of the given resource.
|
When the $diff operation is invoked at the server level (meaning it is invoked against the server base URL), it will compare two arbitrary resources of any type.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ public abstract class AbstractJaxRsBundleProvider extends AbstractJaxRsProvider
|
||||||
private Response execute(final Builder theRequestBuilder, final String methodKey)
|
private Response execute(final Builder theRequestBuilder, final String methodKey)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final JaxRsRequest theRequest = theRequestBuilder.build();
|
final JaxRsRequest theRequest = theRequestBuilder.build();
|
||||||
final BaseMethodBinding<?> method = getBinding(theRequest.getRestOperationType(), methodKey);
|
final BaseMethodBinding method = getBinding(theRequest.getRestOperationType(), methodKey);
|
||||||
try {
|
try {
|
||||||
return (Response) method.invokeServer(this, theRequest);
|
return (Response) method.invokeServer(this, theRequest);
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ public abstract class AbstractJaxRsBundleProvider extends AbstractJaxRsProvider
|
||||||
* @param theBindingKey the key determining the method to be executed (needed for e.g. custom operation)
|
* @param theBindingKey the key determining the method to be executed (needed for e.g. custom operation)
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected BaseMethodBinding<?> getBinding(final RestOperationTypeEnum restOperation, final String theBindingKey) {
|
protected BaseMethodBinding getBinding(final RestOperationTypeEnum restOperation, final String theBindingKey) {
|
||||||
return getBindings().getBinding(restOperation, theBindingKey);
|
return getBindings().getBinding(restOperation, theBindingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,10 @@ import java.io.IOException;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.*;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.ws.rs.*;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
@ -58,24 +56,15 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.CapabilityStatement;
|
import org.hl7.fhir.r4.model.CapabilityStatement;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.OPTIONS;
|
import javax.ws.rs.OPTIONS;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the conformance provider for the jax rs servers. It requires all providers to be registered during startup because the conformance profile is generated during the postconstruct phase.
|
* This is the conformance provider for the jax rs servers. It requires all providers to be registered during startup because the conformance profile is generated during the postconstruct phase.
|
||||||
|
@ -156,7 +145,7 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
||||||
for (Entry<Class<? extends IResourceProvider>, IResourceProvider> provider : providers.entrySet()) {
|
for (Entry<Class<? extends IResourceProvider>, IResourceProvider> provider : providers.entrySet()) {
|
||||||
addProvider(provider.getValue(), provider.getKey());
|
addProvider(provider.getValue(), provider.getKey());
|
||||||
}
|
}
|
||||||
List<BaseMethodBinding<?>> serverBindings = new ArrayList<BaseMethodBinding<?>>();
|
List<BaseMethodBinding> serverBindings = new ArrayList<BaseMethodBinding>();
|
||||||
for (ResourceBinding baseMethodBinding : myResourceNameToBinding.values()) {
|
for (ResourceBinding baseMethodBinding : myResourceNameToBinding.values()) {
|
||||||
serverBindings.addAll(baseMethodBinding.getMethodBindings());
|
serverBindings.addAll(baseMethodBinding.getMethodBindings());
|
||||||
}
|
}
|
||||||
|
@ -269,7 +258,7 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (Method m : ReflectionUtil.getDeclaredMethods(theProviderInterface)) {
|
for (Method m : ReflectionUtil.getDeclaredMethods(theProviderInterface)) {
|
||||||
BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, getFhirContext(), theProvider);
|
BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(m, getFhirContext(), theProvider);
|
||||||
if (foundMethodBinding == null) {
|
if (foundMethodBinding == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,7 @@ implements IRestfulServer<JaxRsRequest>, IResourceProvider {
|
||||||
private Response execute(final Builder theRequestBuilder, final String methodKey)
|
private Response execute(final Builder theRequestBuilder, final String methodKey)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final JaxRsRequest theRequest = theRequestBuilder.build();
|
final JaxRsRequest theRequest = theRequestBuilder.build();
|
||||||
final BaseMethodBinding<?> method = getBinding(theRequest.getRestOperationType(), methodKey);
|
final BaseMethodBinding method = getBinding(theRequest.getRestOperationType(), methodKey);
|
||||||
try {
|
try {
|
||||||
return (Response) method.invokeServer(this, theRequest);
|
return (Response) method.invokeServer(this, theRequest);
|
||||||
}
|
}
|
||||||
|
@ -349,7 +349,7 @@ implements IRestfulServer<JaxRsRequest>, IResourceProvider {
|
||||||
* @param theBindingKey the key determining the method to be executed (needed for e.g. custom operation)
|
* @param theBindingKey the key determining the method to be executed (needed for e.g. custom operation)
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected BaseMethodBinding<?> getBinding(final RestOperationTypeEnum restOperation, final String theBindingKey) {
|
protected BaseMethodBinding getBinding(final RestOperationTypeEnum restOperation, final String theBindingKey) {
|
||||||
return getBindings().getBinding(restOperation, theBindingKey);
|
return getBindings().getBinding(restOperation, theBindingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ public class JaxRsMethodBindings {
|
||||||
/** Static collection of bindings mapped to a class*/
|
/** Static collection of bindings mapped to a class*/
|
||||||
private static final ConcurrentHashMap<Class<?>, JaxRsMethodBindings> classBindings = new ConcurrentHashMap<Class<?>, JaxRsMethodBindings>();
|
private static final ConcurrentHashMap<Class<?>, JaxRsMethodBindings> classBindings = new ConcurrentHashMap<Class<?>, JaxRsMethodBindings>();
|
||||||
/** Static collection of operationBindings mapped to a class */
|
/** Static collection of operationBindings mapped to a class */
|
||||||
private ConcurrentHashMap<RestOperationTypeEnum, ConcurrentHashMap<String, BaseMethodBinding<?>>> operationBindings = new ConcurrentHashMap<RestOperationTypeEnum, ConcurrentHashMap<String,BaseMethodBinding<?>>>();
|
private ConcurrentHashMap<RestOperationTypeEnum, ConcurrentHashMap<String, BaseMethodBinding>> operationBindings = new ConcurrentHashMap<RestOperationTypeEnum, ConcurrentHashMap<String,BaseMethodBinding>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor
|
* The constructor
|
||||||
|
@ -59,7 +58,7 @@ public class JaxRsMethodBindings {
|
||||||
List<Method> declaredMethodsForCurrentProvider = ReflectionUtil.getDeclaredMethods(theProviderClass);
|
List<Method> declaredMethodsForCurrentProvider = ReflectionUtil.getDeclaredMethods(theProviderClass);
|
||||||
declaredMethodsForCurrentProvider.addAll(ReflectionUtil.getDeclaredMethods(theProviderClass.getSuperclass()));
|
declaredMethodsForCurrentProvider.addAll(ReflectionUtil.getDeclaredMethods(theProviderClass.getSuperclass()));
|
||||||
for (final Method m : declaredMethodsForCurrentProvider) {
|
for (final Method m : declaredMethodsForCurrentProvider) {
|
||||||
final BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, theProvider.getFhirContext(), theProvider);
|
final BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(m, theProvider.getFhirContext(), theProvider);
|
||||||
if (foundMethodBinding == null) {
|
if (foundMethodBinding == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +77,7 @@ public class JaxRsMethodBindings {
|
||||||
* @param theBinding the methodbinding
|
* @param theBinding the methodbinding
|
||||||
* @return the key for the methodbinding.
|
* @return the key for the methodbinding.
|
||||||
*/
|
*/
|
||||||
private String getBindingKey(final BaseMethodBinding<?> theBinding) {
|
private String getBindingKey(final BaseMethodBinding theBinding) {
|
||||||
if (theBinding instanceof OperationMethodBinding) {
|
if (theBinding instanceof OperationMethodBinding) {
|
||||||
return ((OperationMethodBinding) theBinding).getName();
|
return ((OperationMethodBinding) theBinding).getName();
|
||||||
} else if (theBinding instanceof SearchMethodBinding) {
|
} else if (theBinding instanceof SearchMethodBinding) {
|
||||||
|
@ -89,8 +88,8 @@ public class JaxRsMethodBindings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMethodBinding(String key, BaseMethodBinding<?> binding) {
|
private void addMethodBinding(String key, BaseMethodBinding binding) {
|
||||||
ConcurrentHashMap<String, BaseMethodBinding<?>> mapByOperation = getMapForOperation(binding.getRestOperationType());
|
ConcurrentHashMap<String, BaseMethodBinding> mapByOperation = getMapForOperation(binding.getRestOperationType());
|
||||||
if (mapByOperation.containsKey(key)) {
|
if (mapByOperation.containsKey(key)) {
|
||||||
throw new IllegalArgumentException(Msg.code(597) + "Multiple Search Method Bindings Found : " + mapByOperation.get(key) + " -- " + binding.getMethod());
|
throw new IllegalArgumentException(Msg.code(597) + "Multiple Search Method Bindings Found : " + mapByOperation.get(key) + " -- " + binding.getMethod());
|
||||||
}
|
}
|
||||||
|
@ -104,10 +103,10 @@ public class JaxRsMethodBindings {
|
||||||
* @param operationType the operation type.
|
* @param operationType the operation type.
|
||||||
* @return the map defined in the operation bindings
|
* @return the map defined in the operation bindings
|
||||||
*/
|
*/
|
||||||
private ConcurrentHashMap<String, BaseMethodBinding<?>> getMapForOperation(RestOperationTypeEnum operationType) {
|
private ConcurrentHashMap<String, BaseMethodBinding> getMapForOperation(RestOperationTypeEnum operationType) {
|
||||||
ConcurrentHashMap<String, BaseMethodBinding<?>> result = operationBindings.get(operationType);
|
ConcurrentHashMap<String, BaseMethodBinding> result = operationBindings.get(operationType);
|
||||||
if(result == null) {
|
if(result == null) {
|
||||||
operationBindings.putIfAbsent(operationType, new ConcurrentHashMap<String, BaseMethodBinding<?>>());
|
operationBindings.putIfAbsent(operationType, new ConcurrentHashMap<String, BaseMethodBinding>());
|
||||||
return getMapForOperation(operationType);
|
return getMapForOperation(operationType);
|
||||||
} else {
|
} else {
|
||||||
return result;
|
return result;
|
||||||
|
@ -122,9 +121,9 @@ public class JaxRsMethodBindings {
|
||||||
* @return the binding defined
|
* @return the binding defined
|
||||||
* @throws NotImplementedOperationException cannot be found
|
* @throws NotImplementedOperationException cannot be found
|
||||||
*/
|
*/
|
||||||
public BaseMethodBinding<?> getBinding(RestOperationTypeEnum operationType, String theBindingKey) {
|
public BaseMethodBinding getBinding(RestOperationTypeEnum operationType, String theBindingKey) {
|
||||||
String bindingKey = StringUtils.defaultIfBlank(theBindingKey, DEFAULT_METHOD_KEY);
|
String bindingKey = StringUtils.defaultIfBlank(theBindingKey, DEFAULT_METHOD_KEY);
|
||||||
ConcurrentHashMap<String, BaseMethodBinding<?>> map = getMapForOperation(operationType);
|
ConcurrentHashMap<String, BaseMethodBinding> map = getMapForOperation(operationType);
|
||||||
if(map == null || !map.containsKey(bindingKey)) {
|
if(map == null || !map.containsKey(bindingKey)) {
|
||||||
throw new NotImplementedOperationException(Msg.code(598) + "Operation not implemented");
|
throw new NotImplementedOperationException(Msg.code(598) + "Operation not implemented");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,10 +20,10 @@ package ca.uhn.fhir.rest.openapi;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.interceptor.api.Hook;
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
@ -58,6 +58,7 @@ import io.swagger.v3.oas.models.responses.ApiResponses;
|
||||||
import io.swagger.v3.oas.models.servers.Server;
|
import io.swagger.v3.oas.models.servers.Server;
|
||||||
import io.swagger.v3.oas.models.tags.Tag;
|
import io.swagger.v3.oas.models.tags.Tag;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40;
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||||
|
@ -127,6 +128,8 @@ public class OpenApiInterceptor {
|
||||||
private final Map<String, String> myResourcePathToClasspath = new HashMap<>();
|
private final Map<String, String> myResourcePathToClasspath = new HashMap<>();
|
||||||
private final Map<String, String> myExtensionToContentType = new HashMap<>();
|
private final Map<String, String> myExtensionToContentType = new HashMap<>();
|
||||||
private String myBannerImage;
|
private String myBannerImage;
|
||||||
|
private String myCssText;
|
||||||
|
private boolean myUseResourcePages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -150,6 +153,7 @@ public class OpenApiInterceptor {
|
||||||
|
|
||||||
private void initResources() {
|
private void initResources() {
|
||||||
setBannerImage(RACCOON_PNG);
|
setBannerImage(RACCOON_PNG);
|
||||||
|
setUseResourcePages(true);
|
||||||
|
|
||||||
addResourcePathToClasspath("/swagger-ui/index.html", "/ca/uhn/fhir/rest/openapi/index.html");
|
addResourcePathToClasspath("/swagger-ui/index.html", "/ca/uhn/fhir/rest/openapi/index.html");
|
||||||
addResourcePathToClasspath("/swagger-ui/" + RACCOON_PNG, "/ca/uhn/fhir/rest/openapi/raccoon.png");
|
addResourcePathToClasspath("/swagger-ui/" + RACCOON_PNG, "/ca/uhn/fhir/rest/openapi/raccoon.png");
|
||||||
|
@ -245,6 +249,15 @@ public class OpenApiInterceptor {
|
||||||
|
|
||||||
|
|
||||||
String resourcePath = requestPath.substring("/swagger-ui/".length());
|
String resourcePath = requestPath.substring("/swagger-ui/".length());
|
||||||
|
|
||||||
|
if (resourcePath.equals("swagger-ui-custom.css") && isNotBlank(myCssText)) {
|
||||||
|
theResponse.setContentType("text/css");
|
||||||
|
theResponse.setStatus(200);
|
||||||
|
theResponse.getWriter().println(myCssText);
|
||||||
|
theResponse.getWriter().close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
try (InputStream resource = ClasspathUtil.loadResourceAsStream("/META-INF/resources/webjars/swagger-ui/" + mySwaggerUiVersion + "/" + resourcePath)) {
|
try (InputStream resource = ClasspathUtil.loadResourceAsStream("/META-INF/resources/webjars/swagger-ui/" + mySwaggerUiVersion + "/" + resourcePath)) {
|
||||||
|
|
||||||
if (resourcePath.endsWith(".js") || resourcePath.endsWith(".map")) {
|
if (resourcePath.endsWith(".js") || resourcePath.endsWith(".map")) {
|
||||||
|
@ -275,12 +288,34 @@ public class OpenApiInterceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String removeTrailingSlash(String theUrl) {
|
public String removeTrailingSlash(String theUrl) {
|
||||||
while(theUrl != null && theUrl.endsWith("/")) {
|
while (theUrl != null && theUrl.endsWith("/")) {
|
||||||
theUrl = theUrl.substring(0, theUrl.length() - 1);
|
theUrl = theUrl.substring(0, theUrl.length() - 1);
|
||||||
}
|
}
|
||||||
return theUrl;
|
return theUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If supplied, this field can be used to provide additional CSS text that should
|
||||||
|
* be loaded by the swagger-ui page. The contents should be raw CSS text, e.g.
|
||||||
|
* <code>
|
||||||
|
* BODY { font-size: 1.1em; }
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
public String getCssText() {
|
||||||
|
return myCssText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If supplied, this field can be used to provide additional CSS text that should
|
||||||
|
* be loaded by the swagger-ui page. The contents should be raw CSS text, e.g.
|
||||||
|
* <code>
|
||||||
|
* BODY { font-size: 1.1em; }
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
public void setCssText(String theCssText) {
|
||||||
|
myCssText = theCssText;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void serveSwaggerUiHtml(ServletRequestDetails theRequestDetails, HttpServletResponse theResponse) throws IOException {
|
private void serveSwaggerUiHtml(ServletRequestDetails theRequestDetails, HttpServletResponse theResponse) throws IOException {
|
||||||
CapabilityStatement cs = getCapabilityStatement(theRequestDetails);
|
CapabilityStatement cs = getCapabilityStatement(theRequestDetails);
|
||||||
|
@ -299,6 +334,8 @@ public class OpenApiInterceptor {
|
||||||
context.setVariable("BANNER_IMAGE_URL", getBannerImage());
|
context.setVariable("BANNER_IMAGE_URL", getBannerImage());
|
||||||
context.setVariable("OPENAPI_DOCS", baseUrl + "/api-docs");
|
context.setVariable("OPENAPI_DOCS", baseUrl + "/api-docs");
|
||||||
context.setVariable("FHIR_VERSION", cs.getFhirVersion().toCode());
|
context.setVariable("FHIR_VERSION", cs.getFhirVersion().toCode());
|
||||||
|
context.setVariable("ADDITIONAL_CSS_TEXT", getCssText());
|
||||||
|
context.setVariable("USE_RESOURCE_PAGES", isUseResourcePages());
|
||||||
context.setVariable("FHIR_VERSION_CODENAME", FhirVersionEnum.forVersionString(cs.getFhirVersion().toCode()).name());
|
context.setVariable("FHIR_VERSION_CODENAME", FhirVersionEnum.forVersionString(cs.getFhirVersion().toCode()).name());
|
||||||
|
|
||||||
String copyright = cs.getCopyright();
|
String copyright = cs.getCopyright();
|
||||||
|
@ -341,7 +378,12 @@ public class OpenApiInterceptor {
|
||||||
context.setVariable("PAGE_NAMES", pageNames);
|
context.setVariable("PAGE_NAMES", pageNames);
|
||||||
context.setVariable("PAGE_NAME_TO_COUNT", resourceToCount);
|
context.setVariable("PAGE_NAME_TO_COUNT", resourceToCount);
|
||||||
|
|
||||||
String page = extractPageName(theRequestDetails, PAGE_SYSTEM);
|
String page;
|
||||||
|
if (isUseResourcePages()) {
|
||||||
|
page = extractPageName(theRequestDetails, PAGE_SYSTEM);
|
||||||
|
} else {
|
||||||
|
page = PAGE_ALL;
|
||||||
|
}
|
||||||
context.setVariable("PAGE", page);
|
context.setVariable("PAGE", page);
|
||||||
|
|
||||||
populateOIDCVariables(theRequestDetails, context);
|
populateOIDCVariables(theRequestDetails, context);
|
||||||
|
@ -828,7 +870,6 @@ public class OpenApiInterceptor {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Content provideContentFhirResource(OpenAPI theOpenApi, FhirContext theExampleFhirContext, Supplier<IBaseResource> theExampleSupplier) {
|
private Content provideContentFhirResource(OpenAPI theOpenApi, FhirContext theExampleFhirContext, Supplier<IBaseResource> theExampleSupplier) {
|
||||||
addSchemaFhirResource(theOpenApi);
|
addSchemaFhirResource(theOpenApi);
|
||||||
Content retVal = new Content();
|
Content retVal = new Content();
|
||||||
|
@ -862,14 +903,36 @@ public class OpenApiInterceptor {
|
||||||
return new ClassLoaderTemplateResource(myResourcePathToClasspath.get("/swagger-ui/index.html"), StandardCharsets.UTF_8.name());
|
return new ClassLoaderTemplateResource(myResourcePathToClasspath.get("/swagger-ui/index.html"), StandardCharsets.UTF_8.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBannerImage(String theBannerImage) {
|
|
||||||
myBannerImage = theBannerImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBannerImage() {
|
public String getBannerImage() {
|
||||||
return myBannerImage;
|
return myBannerImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OpenApiInterceptor setBannerImage(String theBannerImage) {
|
||||||
|
myBannerImage = StringUtils.defaultIfBlank(theBannerImage, null);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUseResourcePages() {
|
||||||
|
return myUseResourcePages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUseResourcePages(boolean theUseResourcePages) {
|
||||||
|
myUseResourcePages = theUseResourcePages;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <T extends Resource> T toCanonicalVersion(IBaseResource theNonCanonical) {
|
||||||
|
IBaseResource canonical;
|
||||||
|
if (theNonCanonical instanceof org.hl7.fhir.dstu3.model.Resource) {
|
||||||
|
canonical = VersionConvertorFactory_30_40.convertResource((org.hl7.fhir.dstu3.model.Resource) theNonCanonical);
|
||||||
|
} else if (theNonCanonical instanceof org.hl7.fhir.r5.model.Resource) {
|
||||||
|
canonical = VersionConvertorFactory_40_50.convertResource((org.hl7.fhir.r5.model.Resource) theNonCanonical);
|
||||||
|
} else {
|
||||||
|
canonical = theNonCanonical;
|
||||||
|
}
|
||||||
|
return (T) canonical;
|
||||||
|
}
|
||||||
|
|
||||||
private class SwaggerUiTemplateResolver implements ITemplateResolver {
|
private class SwaggerUiTemplateResolver implements ITemplateResolver {
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
@ -919,18 +982,5 @@ public class OpenApiInterceptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static <T extends Resource> T toCanonicalVersion(IBaseResource theNonCanonical) {
|
|
||||||
IBaseResource canonical;
|
|
||||||
if (theNonCanonical instanceof org.hl7.fhir.dstu3.model.Resource) {
|
|
||||||
canonical = VersionConvertorFactory_30_40.convertResource((org.hl7.fhir.dstu3.model.Resource) theNonCanonical);
|
|
||||||
} else if (theNonCanonical instanceof org.hl7.fhir.r5.model.Resource) {
|
|
||||||
canonical = VersionConvertorFactory_40_50.convertResource((org.hl7.fhir.r5.model.Resource) theNonCanonical);
|
|
||||||
} else {
|
|
||||||
canonical = theNonCanonical;
|
|
||||||
}
|
|
||||||
return (T) canonical;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,3 +139,8 @@ body
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable the servers dropdown, which is useless here */
|
||||||
|
.swagger-ui .scheme-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
|
@ -4,16 +4,15 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Swagger UI</title>
|
<title>Swagger UI</title>
|
||||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
|
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
|
||||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="./index.css" />
|
<link rel="stylesheet" type="text/css" href="./index.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="./swagger-ui-custom.css" th:if="${ADDITIONAL_CSS_TEXT} != null"/>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
</div>
|
</div>
|
||||||
<div class="banner">
|
<div class="banner">
|
||||||
<img th:src="${BANNER_IMAGE_URL}" style="height: 100px;"/>
|
<img id="banner_img" th:src="${BANNER_IMAGE_URL}" style="height: 100px;" th:if="${BANNER_IMAGE_URL} != null"/>
|
||||||
<h1>[[${DESCRIPTION}]]<br/><span class="version" th:text="${SERVER_NAME} + ' ' + ${SERVER_VERSION}"></span></h1>
|
<h1>[[${DESCRIPTION}]]<br/><span class="version" th:text="${SERVER_NAME} + ' ' + ${SERVER_VERSION}"></span></h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="banner2">
|
<div class="banner2">
|
||||||
|
@ -29,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="bannerCopyright" th:if="${COPYRIGHT_HTML} != null" th:utext="${COPYRIGHT_HTML}">
|
<div class="bannerCopyright" th:if="${COPYRIGHT_HTML} != null" th:utext="${COPYRIGHT_HTML}">
|
||||||
</div>
|
</div>
|
||||||
<div class="banner3">
|
<div class="banner3" th:if="${USE_RESOURCE_PAGES}">
|
||||||
<div class="pageButtons" id="pageButtons">
|
<div class="pageButtons" id="pageButtons">
|
||||||
<a class="pageButton" th:each="pageName : ${PAGE_NAMES}" th:classappend="${pageName} == ${PAGE} ? 'pageButtonSelected' : ''" th:href="@{/swagger-ui/(page=${pageName})}">
|
<a class="pageButton" th:each="pageName : ${PAGE_NAMES}" th:classappend="${pageName} == ${PAGE} ? 'pageButtonSelected' : ''" th:href="@{/swagger-ui/(page=${pageName})}">
|
||||||
[[${pageName}]]
|
[[${pageName}]]
|
||||||
|
|
|
@ -57,11 +57,14 @@ import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
@ -181,6 +184,56 @@ public class OpenApiInterceptorTest {
|
||||||
String url = "http://localhost:" + myServer.getPort() + "/fhir/swagger-ui/";
|
String url = "http://localhost:" + myServer.getPort() + "/fhir/swagger-ui/";
|
||||||
String resp = fetchSwaggerUi(url);
|
String resp = fetchSwaggerUi(url);
|
||||||
assertThat(resp, resp, containsString("<p>This server is copyright <strong>Example Org</strong> 2021</p>"));
|
assertThat(resp, resp, containsString("<p>This server is copyright <strong>Example Org</strong> 2021</p>"));
|
||||||
|
assertThat(resp, resp, not(containsString("swagger-ui-custom.css")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSwaggerUiWithNoBannerUrl() throws IOException {
|
||||||
|
myServer.getRestfulServer().registerInterceptor(new AddResourceCountsInterceptor());
|
||||||
|
myServer.getRestfulServer().registerInterceptor(new OpenApiInterceptor().setBannerImage(""));
|
||||||
|
|
||||||
|
String url = "http://localhost:" + myServer.getPort() + "/fhir/swagger-ui/";
|
||||||
|
String resp = fetchSwaggerUi(url);
|
||||||
|
assertThat(resp, resp, not(containsString("img id=\"banner_img\"")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSwaggerUiWithCustomStylesheet() throws IOException {
|
||||||
|
myServer.getRestfulServer().registerInterceptor(new AddResourceCountsInterceptor());
|
||||||
|
|
||||||
|
OpenApiInterceptor interceptor = new OpenApiInterceptor();
|
||||||
|
interceptor.setCssText("BODY {\nfont-size: 1.1em;\n}");
|
||||||
|
myServer.getRestfulServer().registerInterceptor(interceptor);
|
||||||
|
|
||||||
|
// Fetch Swagger UI HTML
|
||||||
|
String url = "http://localhost:" + myServer.getPort() + "/fhir/swagger-ui/";
|
||||||
|
String resp = fetchSwaggerUi(url);
|
||||||
|
assertThat(resp, resp, containsString("<link rel=\"stylesheet\" type=\"text/css\" href=\"./swagger-ui-custom.css\"/>"));
|
||||||
|
|
||||||
|
// Fetch Custom CSS
|
||||||
|
url = "http://localhost:" + myServer.getPort() + "/fhir/swagger-ui/swagger-ui-custom.css";
|
||||||
|
resp = fetchSwaggerUi(url);
|
||||||
|
String expected = """
|
||||||
|
BODY {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
assertEquals(expected, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSwaggerUiNotPaged() throws IOException {
|
||||||
|
myServer.getRestfulServer().registerInterceptor(new AddResourceCountsInterceptor());
|
||||||
|
|
||||||
|
OpenApiInterceptor interceptor = new OpenApiInterceptor();
|
||||||
|
interceptor.setUseResourcePages(false);
|
||||||
|
myServer.getRestfulServer().registerInterceptor(interceptor);
|
||||||
|
|
||||||
|
// Fetch Swagger UI HTML
|
||||||
|
String url = "http://localhost:" + myServer.getPort() + "/fhir/swagger-ui/";
|
||||||
|
String resp = fetchSwaggerUi(url);
|
||||||
|
List<String> buttonTexts = parsePageButtonTexts(resp, url);
|
||||||
|
assertThat(buttonTexts.toString(), buttonTexts, empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -238,6 +291,10 @@ public class OpenApiInterceptorTest {
|
||||||
private List<String> parsePageButtonTexts(String resp, String url) throws IOException {
|
private List<String> parsePageButtonTexts(String resp, String url) throws IOException {
|
||||||
HtmlPage html = HtmlUtil.parseAsHtml(resp, new URL(url));
|
HtmlPage html = HtmlUtil.parseAsHtml(resp, new URL(url));
|
||||||
HtmlDivision pageButtons = (HtmlDivision) html.getElementById("pageButtons");
|
HtmlDivision pageButtons = (HtmlDivision) html.getElementById("pageButtons");
|
||||||
|
if (pageButtons == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
List<String> buttonTexts = new ArrayList<>();
|
List<String> buttonTexts = new ArrayList<>();
|
||||||
for (DomElement next : pageButtons.getChildElements()) {
|
for (DomElement next : pageButtons.getChildElements()) {
|
||||||
buttonTexts.add(next.asNormalizedText());
|
buttonTexts.add(next.asNormalizedText());
|
||||||
|
|
|
@ -32,13 +32,13 @@ public interface IRestfulServerUtil {
|
||||||
Object getResourceParameter(
|
Object getResourceParameter(
|
||||||
RequestDetails requestDetails,
|
RequestDetails requestDetails,
|
||||||
Mode myMode,
|
Mode myMode,
|
||||||
BaseMethodBinding<?> theMethodBinding,
|
BaseMethodBinding theMethodBinding,
|
||||||
Class<? extends IBaseResource> myResourceType);
|
Class<? extends IBaseResource> myResourceType);
|
||||||
|
|
||||||
Object getRequestResource(RequestDetails theRequest, ParamStyle myParamStyle, Class<? extends IBaseResource> myResourceBundleType);
|
Object getRequestResource(RequestDetails theRequest, ParamStyle myParamStyle, Class<? extends IBaseResource> myResourceBundleType);
|
||||||
|
|
||||||
<T extends IBaseResource> T loadResourceFromRequest(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding, Class<T> theResourceType);
|
<T extends IBaseResource> T loadResourceFromRequest(RequestDetails theRequest, BaseMethodBinding theMethodBinding, Class<T> theResourceType);
|
||||||
|
|
||||||
IBaseResource parseResourceFromRequest(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding, Class<? extends IBaseResource> theResourceType);
|
IBaseResource parseResourceFromRequest(RequestDetails theRequest, BaseMethodBinding theMethodBinding, Class<? extends IBaseResource> theResourceType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.MethodMatchEnum;
|
import ca.uhn.fhir.rest.server.method.MethodMatchEnum;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -35,7 +36,7 @@ public class ResourceBinding {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceBinding.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceBinding.class);
|
||||||
|
|
||||||
private String resourceName;
|
private String resourceName;
|
||||||
private LinkedList<BaseMethodBinding<?>> myMethodBindings = new LinkedList<>();
|
private LinkedList<BaseMethodBinding> myMethodBindings = new LinkedList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -44,7 +45,7 @@ public class ResourceBinding {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseMethodBinding<?> getMethod(RequestDetails theRequest) {
|
public BaseMethodBinding getMethod(RequestDetails theRequest) {
|
||||||
if (null == myMethodBindings) {
|
if (null == myMethodBindings) {
|
||||||
ourLog.warn("No methods exist for resource: {}", resourceName);
|
ourLog.warn("No methods exist for resource: {}", resourceName);
|
||||||
return null;
|
return null;
|
||||||
|
@ -56,10 +57,10 @@ public class ResourceBinding {
|
||||||
* Look for the method with the highest match strength
|
* Look for the method with the highest match strength
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BaseMethodBinding<?> matchedMethod = null;
|
BaseMethodBinding matchedMethod = null;
|
||||||
MethodMatchEnum matchedMethodStrength = null;
|
MethodMatchEnum matchedMethodStrength = null;
|
||||||
|
|
||||||
for (BaseMethodBinding<?> rm : myMethodBindings) {
|
for (BaseMethodBinding rm : myMethodBindings) {
|
||||||
MethodMatchEnum nextMethodMatch = rm.incomingServerRequestMatchesMethod(theRequest);
|
MethodMatchEnum nextMethodMatch = rm.incomingServerRequestMatchesMethod(theRequest);
|
||||||
if (nextMethodMatch != MethodMatchEnum.NONE) {
|
if (nextMethodMatch != MethodMatchEnum.NONE) {
|
||||||
if (matchedMethodStrength == null || matchedMethodStrength.ordinal() < nextMethodMatch.ordinal()) {
|
if (matchedMethodStrength == null || matchedMethodStrength.ordinal() < nextMethodMatch.ordinal()) {
|
||||||
|
@ -83,11 +84,11 @@ public class ResourceBinding {
|
||||||
this.resourceName = resourceName;
|
this.resourceName = resourceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BaseMethodBinding<?>> getMethodBindings() {
|
public List<BaseMethodBinding> getMethodBindings() {
|
||||||
return myMethodBindings;
|
return myMethodBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMethod(BaseMethodBinding<?> method) {
|
public void addMethod(BaseMethodBinding method) {
|
||||||
this.myMethodBindings.push(method);
|
this.myMethodBindings.push(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.ConformanceMethodBinding;
|
import ca.uhn.fhir.rest.server.method.ConformanceMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.MethodMatchEnum;
|
import ca.uhn.fhir.rest.server.method.MethodMatchEnum;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.tenant.ITenantIdentificationStrategy;
|
import ca.uhn.fhir.rest.server.tenant.ITenantIdentificationStrategy;
|
||||||
|
@ -77,6 +78,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.UnavailableException;
|
import javax.servlet.UnavailableException;
|
||||||
import javax.servlet.http.HttpServlet;
|
import javax.servlet.http.HttpServlet;
|
||||||
|
@ -264,7 +266,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BaseMethodBinding<?>> getGlobalBindings() {
|
private List<BaseMethodBinding> getGlobalBindings() {
|
||||||
return myGlobalBinding.getMethodBindings();
|
return myGlobalBinding.getMethodBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,11 +372,11 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
* Figure out and return whichever method binding is appropriate for
|
* Figure out and return whichever method binding is appropriate for
|
||||||
* the given request
|
* the given request
|
||||||
*/
|
*/
|
||||||
public BaseMethodBinding<?> determineResourceMethod(RequestDetails requestDetails, String requestPath) {
|
public BaseMethodBinding determineResourceMethod(RequestDetails requestDetails, String requestPath) {
|
||||||
RequestTypeEnum requestType = requestDetails.getRequestType();
|
RequestTypeEnum requestType = requestDetails.getRequestType();
|
||||||
|
|
||||||
ResourceBinding resourceBinding = null;
|
ResourceBinding resourceBinding = null;
|
||||||
BaseMethodBinding<?> resourceMethod = null;
|
BaseMethodBinding resourceMethod = null;
|
||||||
String resourceName = requestDetails.getResourceName();
|
String resourceName = requestDetails.getResourceName();
|
||||||
if (myServerConformanceMethod.incomingServerRequestMatchesMethod(requestDetails) != MethodMatchEnum.NONE) {
|
if (myServerConformanceMethod.incomingServerRequestMatchesMethod(requestDetails) != MethodMatchEnum.NONE) {
|
||||||
resourceMethod = myServerConformanceMethod;
|
resourceMethod = myServerConformanceMethod;
|
||||||
|
@ -466,7 +468,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (Method m : ReflectionUtil.getDeclaredMethods(clazz)) {
|
for (Method m : ReflectionUtil.getDeclaredMethods(clazz)) {
|
||||||
BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, getFhirContext(), theProvider);
|
BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(m, getFhirContext(), theProvider);
|
||||||
if (foundMethodBinding == null) {
|
if (foundMethodBinding == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -489,6 +491,18 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
ourLog.trace("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
|
ourLog.trace("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
|
||||||
|
|
||||||
|
// Interceptor call: SERVER_PROVIDER_METHOD_BOUND
|
||||||
|
if (myInterceptorService.hasHooks(Pointcut.SERVER_PROVIDER_METHOD_BOUND)) {
|
||||||
|
HookParams params = new HookParams()
|
||||||
|
.add(BaseMethodBinding.class, foundMethodBinding);
|
||||||
|
BaseMethodBinding newMethodBinding = (BaseMethodBinding) myInterceptorService.callHooksAndReturnObject(Pointcut.SERVER_PROVIDER_METHOD_BOUND, params);
|
||||||
|
if (newMethodBinding == null) {
|
||||||
|
ourLog.info("Method binding {} was discarded by interceptor and will not be registered", foundMethodBinding);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foundMethodBinding = newMethodBinding;
|
||||||
|
}
|
||||||
|
|
||||||
String resourceName = foundMethodBinding.getResourceName();
|
String resourceName = foundMethodBinding.getResourceName();
|
||||||
ResourceBinding resourceBinding;
|
ResourceBinding resourceBinding;
|
||||||
if (resourceName == null) {
|
if (resourceName == null) {
|
||||||
|
@ -515,7 +529,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
Package pack = annotation.annotationType().getPackage();
|
Package pack = annotation.annotationType().getPackage();
|
||||||
if (pack.equals(IdParam.class.getPackage())) {
|
if (pack.equals(IdParam.class.getPackage())) {
|
||||||
if (!allowableParams.contains(annotation.annotationType())) {
|
if (!allowableParams.contains(annotation.annotationType())) {
|
||||||
throw new ConfigurationException(Msg.code(292) + "Method[" + m.toString() + "] is not allowed to have a parameter annotated with " + annotation);
|
throw new ConfigurationException(Msg.code(292) + "Method[" + m + "] is not allowed to have a parameter annotated with " + annotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -823,10 +837,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
return myResourceNameToBinding.values();
|
return myResourceNameToBinding.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<BaseMethodBinding<?>> getProviderMethodBindings(Object theProvider) {
|
public Collection<BaseMethodBinding> getProviderMethodBindings(Object theProvider) {
|
||||||
Set<BaseMethodBinding<?>> retVal = new HashSet<>();
|
Set<BaseMethodBinding> retVal = new HashSet<>();
|
||||||
for (ResourceBinding resourceBinding : getResourceBindings()) {
|
for (ResourceBinding resourceBinding : getResourceBindings()) {
|
||||||
for (BaseMethodBinding<?> methodBinding : resourceBinding.getMethodBindings()) {
|
for (BaseMethodBinding methodBinding : resourceBinding.getMethodBindings()) {
|
||||||
if (theProvider.equals(methodBinding.getProvider())) {
|
if (theProvider.equals(methodBinding.getProvider())) {
|
||||||
retVal.add(methodBinding);
|
retVal.add(methodBinding);
|
||||||
}
|
}
|
||||||
|
@ -904,7 +918,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
* internal to HAPI and developers generally do not need to interact with it. Use
|
* internal to HAPI and developers generally do not need to interact with it. Use
|
||||||
* with caution, as it may change.
|
* with caution, as it may change.
|
||||||
*/
|
*/
|
||||||
public List<BaseMethodBinding<?>> getServerBindings() {
|
public List<BaseMethodBinding> getServerBindings() {
|
||||||
return myServerBinding.getMethodBindings();
|
return myServerBinding.getMethodBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,7 +1139,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
|
|
||||||
validateRequest(requestDetails);
|
validateRequest(requestDetails);
|
||||||
|
|
||||||
BaseMethodBinding<?> resourceMethod = determineResourceMethod(requestDetails, requestPath);
|
BaseMethodBinding resourceMethod = determineResourceMethod(requestDetails, requestPath);
|
||||||
|
|
||||||
RestOperationTypeEnum operation = resourceMethod.getRestOperationType(requestDetails);
|
RestOperationTypeEnum operation = resourceMethod.getRestOperationType(requestDetails);
|
||||||
requestDetails.setRestOperationType(operation);
|
requestDetails.setRestOperationType(operation);
|
||||||
|
@ -1693,7 +1707,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
/*
|
/*
|
||||||
* Inner method to actually register theProviders
|
* Inner method to actually register theProviders
|
||||||
*/
|
*/
|
||||||
protected void registerProviders(Collection<?> theProviders, boolean inInit) {
|
protected void registerProviders(@Nullable Collection<?> theProviders, boolean inInit) {
|
||||||
Validate.noNullElements(theProviders, "theProviders must not contain any null elements");
|
Validate.noNullElements(theProviders, "theProviders must not contain any null elements");
|
||||||
|
|
||||||
List<IResourceProvider> newResourceProviders = new ArrayList<>();
|
List<IResourceProvider> newResourceProviders = new ArrayList<>();
|
||||||
|
@ -1772,8 +1786,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Iterator<BaseMethodBinding<?>> it = resourceBinding.getMethodBindings().iterator(); it.hasNext(); ) {
|
for (Iterator<BaseMethodBinding> it = resourceBinding.getMethodBindings().iterator(); it.hasNext(); ) {
|
||||||
BaseMethodBinding<?> binding = it.next();
|
BaseMethodBinding binding = it.next();
|
||||||
if (theProvider.equals(binding.getProvider())) {
|
if (theProvider.equals(binding.getProvider())) {
|
||||||
it.remove();
|
it.remove();
|
||||||
ourLog.info("{} binding of {} was removed", resourceName, binding);
|
ourLog.info("{} binding of {} was removed", resourceName, binding);
|
||||||
|
@ -1798,7 +1812,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
*/
|
*/
|
||||||
private void removeResourceMethods(Object theProvider, Class<?> clazz, Collection<String> resourceNames) throws ConfigurationException {
|
private void removeResourceMethods(Object theProvider, Class<?> clazz, Collection<String> resourceNames) throws ConfigurationException {
|
||||||
for (Method m : ReflectionUtil.getDeclaredMethods(clazz)) {
|
for (Method m : ReflectionUtil.getDeclaredMethods(clazz)) {
|
||||||
BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, getFhirContext(), theProvider);
|
BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(m, getFhirContext(), theProvider);
|
||||||
if (foundMethodBinding == null) {
|
if (foundMethodBinding == null) {
|
||||||
continue; // not a bound method
|
continue; // not a bound method
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,12 +63,11 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
public class RestfulServerConfiguration implements ISearchParamRegistry {
|
public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
|
|
||||||
public static final String GLOBAL = "GLOBAL";
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(RestfulServerConfiguration.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(RestfulServerConfiguration.class);
|
||||||
private Collection<ResourceBinding> resourceBindings;
|
private Collection<ResourceBinding> myResourceBindings;
|
||||||
private List<BaseMethodBinding<?>> serverBindings;
|
private List<BaseMethodBinding> myServerBindings;
|
||||||
private List<BaseMethodBinding<?>> myGlobalBindings;
|
private List<BaseMethodBinding> myGlobalBindings;
|
||||||
private Map<String, Class<? extends IBaseResource>> resourceNameToSharedSupertype;
|
private Map<String, Class<? extends IBaseResource>> myResourceNameToSharedSupertype;
|
||||||
private String myImplementationDescription;
|
private String myImplementationDescription;
|
||||||
private String myServerName = "HAPI FHIR";
|
private String myServerName = "HAPI FHIR";
|
||||||
private String myServerVersion = VersionUtil.getVersion();
|
private String myServerVersion = VersionUtil.getVersion();
|
||||||
|
@ -89,7 +88,7 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
* @return the resourceBindings
|
* @return the resourceBindings
|
||||||
*/
|
*/
|
||||||
public Collection<ResourceBinding> getResourceBindings() {
|
public Collection<ResourceBinding> getResourceBindings() {
|
||||||
return resourceBindings;
|
return myResourceBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,7 +97,7 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
* @param resourceBindings the resourceBindings to set
|
* @param resourceBindings the resourceBindings to set
|
||||||
*/
|
*/
|
||||||
public RestfulServerConfiguration setResourceBindings(Collection<ResourceBinding> resourceBindings) {
|
public RestfulServerConfiguration setResourceBindings(Collection<ResourceBinding> resourceBindings) {
|
||||||
this.resourceBindings = resourceBindings;
|
this.myResourceBindings = resourceBindings;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,24 +106,24 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
*
|
*
|
||||||
* @return the serverBindings
|
* @return the serverBindings
|
||||||
*/
|
*/
|
||||||
public List<BaseMethodBinding<?>> getServerBindings() {
|
public List<BaseMethodBinding> getServerBindings() {
|
||||||
return serverBindings;
|
return myServerBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the theServerBindings
|
* Set the theServerBindings
|
||||||
*/
|
*/
|
||||||
public RestfulServerConfiguration setServerBindings(List<BaseMethodBinding<?>> theServerBindings) {
|
public RestfulServerConfiguration setServerBindings(List<BaseMethodBinding> theServerBindings) {
|
||||||
this.serverBindings = theServerBindings;
|
this.myServerBindings = theServerBindings;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Class<? extends IBaseResource>> getNameToSharedSupertype() {
|
public Map<String, Class<? extends IBaseResource>> getNameToSharedSupertype() {
|
||||||
return resourceNameToSharedSupertype;
|
return myResourceNameToSharedSupertype;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestfulServerConfiguration setNameToSharedSupertype(Map<String, Class<? extends IBaseResource>> resourceNameToSharedSupertype) {
|
public RestfulServerConfiguration setNameToSharedSupertype(Map<String, Class<? extends IBaseResource>> resourceNameToSharedSupertype) {
|
||||||
this.resourceNameToSharedSupertype = resourceNameToSharedSupertype;
|
this.myResourceNameToSharedSupertype = resourceNameToSharedSupertype;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,8 +247,8 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
IdentityHashMap<OperationMethodBinding, String> operationBindingToId = new IdentityHashMap<>();
|
IdentityHashMap<OperationMethodBinding, String> operationBindingToId = new IdentityHashMap<>();
|
||||||
HashMap<String, List<OperationMethodBinding>> operationIdToBindings = new HashMap<>();
|
HashMap<String, List<OperationMethodBinding>> operationIdToBindings = new HashMap<>();
|
||||||
|
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = collectMethodBindings();
|
Map<String, List<BaseMethodBinding>> resourceToMethods = collectMethodBindings();
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceToMethods
|
List<BaseMethodBinding> methodBindings = resourceToMethods
|
||||||
.values()
|
.values()
|
||||||
.stream().flatMap(t -> t.stream())
|
.stream().flatMap(t -> t.stream())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
@ -258,7 +257,7 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
ListMultimap<String, OperationMethodBinding> nameToOperationMethodBindings = ArrayListMultimap.create();
|
ListMultimap<String, OperationMethodBinding> nameToOperationMethodBindings = ArrayListMultimap.create();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : methodBindings) {
|
for (BaseMethodBinding nextMethodBinding : methodBindings) {
|
||||||
if (nextMethodBinding instanceof OperationMethodBinding) {
|
if (nextMethodBinding instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
||||||
nameToOperationMethodBindings.put(methodBinding.getName(), methodBinding);
|
nameToOperationMethodBindings.put(methodBinding.getName(), methodBinding);
|
||||||
|
@ -332,7 +331,7 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
nextMethodBindings.forEach(t->operationBindingToId.put(t, operationId));
|
nextMethodBindings.forEach(t->operationBindingToId.put(t, operationId));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : methodBindings) {
|
for (BaseMethodBinding nextMethodBinding : methodBindings) {
|
||||||
if (nextMethodBinding instanceof OperationMethodBinding) {
|
if (nextMethodBinding instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
||||||
if (operationBindingToId.containsKey(methodBinding)) {
|
if (operationBindingToId.containsKey(methodBinding)) {
|
||||||
|
@ -353,18 +352,18 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
return new Bindings(namedSearchMethodBindingToName, searchNameToBindings, operationIdToBindings, operationBindingToId);
|
return new Bindings(namedSearchMethodBindingToName, searchNameToBindings, operationIdToBindings, operationBindingToId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, List<BaseMethodBinding<?>>> collectMethodBindings() {
|
public Map<String, List<BaseMethodBinding>> collectMethodBindings() {
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = new TreeMap<>();
|
Map<String, List<BaseMethodBinding>> resourceToMethods = new TreeMap<>();
|
||||||
for (ResourceBinding next : getResourceBindings()) {
|
for (ResourceBinding next : getResourceBindings()) {
|
||||||
String resourceName = next.getResourceName();
|
String resourceName = next.getResourceName();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : next.getMethodBindings()) {
|
for (BaseMethodBinding nextMethodBinding : next.getMethodBindings()) {
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<>());
|
resourceToMethods.put(resourceName, new ArrayList<>());
|
||||||
}
|
}
|
||||||
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : getServerBindings()) {
|
for (BaseMethodBinding nextMethodBinding : getServerBindings()) {
|
||||||
String resourceName = "";
|
String resourceName = "";
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<>());
|
resourceToMethods.put(resourceName, new ArrayList<>());
|
||||||
|
@ -374,11 +373,11 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
return resourceToMethods;
|
return resourceToMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BaseMethodBinding<?>> getGlobalBindings() {
|
public List<BaseMethodBinding> getGlobalBindings() {
|
||||||
return myGlobalBindings;
|
return myGlobalBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGlobalBindings(List<BaseMethodBinding<?>> theGlobalBindings) {
|
public void setGlobalBindings(List<BaseMethodBinding> theGlobalBindings) {
|
||||||
myGlobalBindings = theGlobalBindings;
|
myGlobalBindings = theGlobalBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +402,7 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
||||||
scanner.register(resourceClass);
|
scanner.register(resourceClass);
|
||||||
});
|
});
|
||||||
|
|
||||||
resourceNameToSharedSupertype = resourceNameToScanner.entrySet().stream()
|
myResourceNameToSharedSupertype = resourceNameToScanner.entrySet().stream()
|
||||||
.filter(entry -> entry.getValue().getLowestCommonSuperclass().isPresent())
|
.filter(entry -> entry.getValue().getLowestCommonSuperclass().isPresent())
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
entry -> entry.getKey(),
|
entry -> entry.getKey(),
|
||||||
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Server Framework
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.server.method.OperationMethodBinding;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interceptor can be used to selectively block specific interactions/operations from
|
||||||
|
* the server's capabilities. This interceptor must be configured and registered to a
|
||||||
|
* {@link ca.uhn.fhir.rest.server.RestfulServer} prior to any resource provider
|
||||||
|
* classes being registered to it. This interceptor will then examine any
|
||||||
|
* provider classes being registered and may choose to discard some or all
|
||||||
|
* of the method bindings on each provider.
|
||||||
|
* <p>
|
||||||
|
* For example, if this interceptor is configured to block resource creation, then
|
||||||
|
* when a resource provider is registered that has both a
|
||||||
|
* {@link ca.uhn.fhir.rest.annotation.Read @Read} method and a
|
||||||
|
* {@link ca.uhn.fhir.rest.annotation.Create @Create} method, the
|
||||||
|
* create method will be ignored and not bound.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Note: This interceptor is not a security interceptor! It can be used to remove
|
||||||
|
* writes capabilities from a FHIR endpoint (for example) but it does not guarantee
|
||||||
|
* that writes won't be possible. Security rules should be enforced using
|
||||||
|
* {@link ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor} or
|
||||||
|
* a similar strategy. However, this interceptor can be useful in order to
|
||||||
|
* clarify the intent of an endpoint to the outside world. Of particular note,
|
||||||
|
* even if a create method has been blocked from binding by this interceptor,
|
||||||
|
* it may still be possible to create resources via a FHIR transaction unless
|
||||||
|
* proper security has been implemented.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Use {@link Builder new Builder()} to create a new instance of this class.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @see Builder#addAllowedSpec(String) to add allowed interactions
|
||||||
|
* @since 6.2.0
|
||||||
|
*/
|
||||||
|
@Interceptor
|
||||||
|
public class InteractionBlockingInterceptor {
|
||||||
|
|
||||||
|
public static final Set<RestOperationTypeEnum> ALLOWED_OP_TYPES;
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(InteractionBlockingInterceptor.class);
|
||||||
|
|
||||||
|
static {
|
||||||
|
Set<RestOperationTypeEnum> allowedOpTypes = new TreeSet<>();
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.META);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.META_ADD);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.META_DELETE);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.PATCH);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.READ);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.CREATE);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.UPDATE);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.DELETE);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.BATCH);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.TRANSACTION);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.VALIDATE);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.SEARCH_TYPE);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.HISTORY_TYPE);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.HISTORY_INSTANCE);
|
||||||
|
allowedOpTypes.add(RestOperationTypeEnum.HISTORY_SYSTEM);
|
||||||
|
ALLOWED_OP_TYPES = Collections.unmodifiableSet(allowedOpTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Set<String> myAllowedKeys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
private InteractionBlockingInterceptor(@Nonnull Builder theBuilder) {
|
||||||
|
myAllowedKeys = theBuilder.myAllowedKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Hook(Pointcut.SERVER_PROVIDER_METHOD_BOUND)
|
||||||
|
public BaseMethodBinding bindMethod(BaseMethodBinding theMethodBinding) {
|
||||||
|
|
||||||
|
boolean allowed = true;
|
||||||
|
String resourceName = theMethodBinding.getResourceName();
|
||||||
|
RestOperationTypeEnum restOperationType = theMethodBinding.getRestOperationType();
|
||||||
|
switch (restOperationType) {
|
||||||
|
case EXTENDED_OPERATION_SERVER:
|
||||||
|
case EXTENDED_OPERATION_TYPE:
|
||||||
|
case EXTENDED_OPERATION_INSTANCE: {
|
||||||
|
OperationMethodBinding operationMethodBinding = (OperationMethodBinding) theMethodBinding;
|
||||||
|
if (!myAllowedKeys.isEmpty()) {
|
||||||
|
if (!myAllowedKeys.contains(operationMethodBinding.getName())) {
|
||||||
|
allowed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (restOperationType == RestOperationTypeEnum.VREAD) {
|
||||||
|
restOperationType = RestOperationTypeEnum.READ;
|
||||||
|
}
|
||||||
|
String key = toKey(resourceName, restOperationType);
|
||||||
|
if (!myAllowedKeys.isEmpty()) {
|
||||||
|
if (!myAllowedKeys.contains(key)) {
|
||||||
|
allowed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allowed) {
|
||||||
|
ourLog.info("Skipping method binding for {}:{} provided by {}", resourceName, restOperationType, theMethodBinding.getMethod());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return theMethodBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String toKey(String theResourceType, RestOperationTypeEnum theRestOperationTypeEnum) {
|
||||||
|
if (isBlank(theResourceType)) {
|
||||||
|
return theRestOperationTypeEnum.getCode();
|
||||||
|
}
|
||||||
|
return theResourceType + ":" + theRestOperationTypeEnum.getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private final Set<String> myAllowedKeys = new HashSet<>();
|
||||||
|
private final FhirContext myCtx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public Builder(@Nonnull FhirContext theCtx) {
|
||||||
|
Validate.notNull(theCtx, "theCtx must not be null");
|
||||||
|
myCtx = theCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an interaction or operation that will be permitted. Allowable formats
|
||||||
|
* are:
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* <b>[resourceType]:[interaction]</b> - Use this form to allow type- and instance-level interactions, such as
|
||||||
|
* <code>create</code>, <code>read</code>, and <code>patch</code>. For example, the spec <code>Patient:create</code>
|
||||||
|
* allows the Patient-level create operation (i.e. <code>POST /Patient</code>).
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* <b>$[operation-name]</b> - Use this form to allow operations (at any level) by name. For example, the spec
|
||||||
|
* <code>$diff</code> permits the <a href="https://hapifhir.io/hapi-fhir/docs/server_jpa/diff.html">Diff Operation</a>
|
||||||
|
* to be applied at both the server- and instance-level.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* Note that the spec does not differentiate between the <code>read</code> and <code>vread</code> interactions. If one
|
||||||
|
* is permitted the other will also be permitted.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Builder addAllowedSpec(String theSpec) {
|
||||||
|
Validate.notBlank(theSpec, "theSpec must not be null or blank");
|
||||||
|
|
||||||
|
if (theSpec.startsWith("$")) {
|
||||||
|
addAllowedOperation(theSpec);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int colonIdx = theSpec.indexOf(':');
|
||||||
|
Validate.isTrue(colonIdx > 0, "Invalid interaction allowed spec: %s", theSpec);
|
||||||
|
|
||||||
|
String resourceName = theSpec.substring(0, colonIdx);
|
||||||
|
String interactionName = theSpec.substring(colonIdx + 1);
|
||||||
|
RestOperationTypeEnum interaction = RestOperationTypeEnum.forCode(interactionName);
|
||||||
|
Validate.notNull(interaction, "Unknown interaction %s in spec %s", interactionName, theSpec);
|
||||||
|
addAllowedInteraction(resourceName, interaction);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an interaction that will be permitted.
|
||||||
|
*/
|
||||||
|
private void addAllowedInteraction(String theResourceType, RestOperationTypeEnum theInteractionType) {
|
||||||
|
Validate.notBlank(theResourceType, "theResourceType must not be null or blank");
|
||||||
|
Validate.notNull(theInteractionType, "theInteractionType must not be null");
|
||||||
|
Validate.isTrue(ALLOWED_OP_TYPES.contains(theInteractionType), "Operation type %s can not be used as an allowable rule", theInteractionType);
|
||||||
|
Validate.isTrue(myCtx.getResourceType(theResourceType) != null, "Unknown resource type: %s");
|
||||||
|
String key = toKey(theResourceType, theInteractionType);
|
||||||
|
myAllowedKeys.add(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAllowedOperation(String theOperationName) {
|
||||||
|
Validate.notBlank(theOperationName, "theOperationName must not be null or blank");
|
||||||
|
Validate.isTrue(theOperationName.startsWith("$"), "Invalid operation name: %s", theOperationName);
|
||||||
|
myAllowedKeys.add(theOperationName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InteractionBlockingInterceptor build() {
|
||||||
|
return new InteractionBlockingInterceptor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -469,7 +469,7 @@ public class SearchNarrowingInterceptor {
|
||||||
String url = theModifiableBundleEntry.getRequestUrl();
|
String url = theModifiableBundleEntry.getRequestUrl();
|
||||||
|
|
||||||
ServletSubRequestDetails subServletRequestDetails = ServletRequestUtil.getServletSubRequestDetails(myRequestDetails, url, paramValues);
|
ServletSubRequestDetails subServletRequestDetails = ServletRequestUtil.getServletSubRequestDetails(myRequestDetails, url, paramValues);
|
||||||
BaseMethodBinding<?> method = subServletRequestDetails.getServer().determineResourceMethod(subServletRequestDetails, url);
|
BaseMethodBinding method = subServletRequestDetails.getServer().determineResourceMethod(subServletRequestDetails, url);
|
||||||
RestOperationTypeEnum restOperationType = method.getRestOperationType();
|
RestOperationTypeEnum restOperationType = method.getRestOperationType();
|
||||||
subServletRequestDetails.setRestOperationType(restOperationType);
|
subServletRequestDetails.setRestOperationType(restOperationType);
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
public abstract class BaseMethodBinding<T> {
|
public abstract class BaseMethodBinding {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseMethodBinding.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseMethodBinding.class);
|
||||||
private final List<BaseQueryParameter> myQueryParameters;
|
private final List<BaseQueryParameter> myQueryParameters;
|
||||||
|
@ -331,7 +331,7 @@ public abstract class BaseMethodBinding<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static BaseMethodBinding<?> bindMethod(Method theMethod, FhirContext theContext, Object theProvider) {
|
public static BaseMethodBinding bindMethod(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||||
Read read = theMethod.getAnnotation(Read.class);
|
Read read = theMethod.getAnnotation(Read.class);
|
||||||
Search search = theMethod.getAnnotation(Search.class);
|
Search search = theMethod.getAnnotation(Search.class);
|
||||||
Metadata conformance = theMethod.getAnnotation(Metadata.class);
|
Metadata conformance = theMethod.getAnnotation(Metadata.class);
|
||||||
|
|
|
@ -44,7 +44,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
|
|
||||||
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
|
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding {
|
||||||
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
|
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
|
||||||
|
|
||||||
private boolean myReturnVoid;
|
private boolean myReturnVoid;
|
||||||
|
|
|
@ -95,7 +95,7 @@ public abstract class BaseQueryParameter implements IParameter {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
|
|
||||||
List<QualifiedParamList> paramList = new ArrayList<>();
|
List<QualifiedParamList> paramList = new ArrayList<>();
|
||||||
String name = getName();
|
String name = getName();
|
||||||
|
|
|
@ -72,7 +72,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Object> {
|
public abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReturningMethodBinding.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReturningMethodBinding.class);
|
||||||
|
|
||||||
private MethodReturnTypeEnum myMethodReturnType;
|
private MethodReturnTypeEnum myMethodReturnType;
|
||||||
|
|
|
@ -53,7 +53,7 @@ class ConditionalParamBinder implements IParameter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return theRequest.getConditionalUrl(theMethodBinding.getRestOperationType());
|
return theRequest.getConditionalUrl(theMethodBinding.getRestOperationType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class CountParameter implements IParameter {
|
||||||
private Class<?> myType;
|
private Class<?> myType;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
String[] countParam = theRequest.getParameters().get(Constants.PARAM_COUNT);
|
String[] countParam = theRequest.getParameters().get(Constants.PARAM_COUNT);
|
||||||
if (countParam != null) {
|
if (countParam != null) {
|
||||||
if (countParam.length > 0) {
|
if (countParam.length > 0) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class ElementsParameter implements IParameter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
Set<String> value = getElementsValueOrNull(theRequest, false);
|
Set<String> value = getElementsValueOrNull(theRequest, false);
|
||||||
if (value == null || value.isEmpty()) {
|
if (value == null || value.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class GraphQLQueryBodyParameter implements IParameter {
|
||||||
private Class<?> myType;
|
private Class<?> myType;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
String ctValue = defaultString(theRequest.getHeader(Constants.HEADER_CONTENT_TYPE));
|
String ctValue = defaultString(theRequest.getHeader(Constants.HEADER_CONTENT_TYPE));
|
||||||
Reader requestReader = createRequestReader(theRequest);
|
Reader requestReader = createRequestReader(theRequest);
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,11 @@ package ca.uhn.fhir.rest.server.method;
|
||||||
|
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Count;
|
import ca.uhn.fhir.rest.annotation.Count;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -40,7 +36,7 @@ public class GraphQLQueryUrlParameter implements IParameter {
|
||||||
private Class<?> myType;
|
private Class<?> myType;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
String[] queryParams = theRequest.getParameters().get(Constants.PARAM_GRAPHQL_QUERY);
|
String[] queryParams = theRequest.getParameters().get(Constants.PARAM_GRAPHQL_QUERY);
|
||||||
String retVal = null;
|
String retVal = null;
|
||||||
if (queryParams != null) {
|
if (queryParams != null) {
|
||||||
|
|
|
@ -41,7 +41,7 @@ public interface IParameter {
|
||||||
* @param theMethodBinding TODO
|
* @param theMethodBinding TODO
|
||||||
* @return Returns the argument object as it will be passed to the IResourceProvider method.
|
* @return Returns the argument object as it will be passed to the IResourceProvider method.
|
||||||
*/
|
*/
|
||||||
Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException;
|
Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException;
|
||||||
|
|
||||||
void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType);
|
void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
class InterceptorBroadcasterParameter implements IParameter {
|
class InterceptorBroadcasterParameter implements IParameter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return theRequest.getInterceptorBroadcaster();
|
return theRequest.getInterceptorBroadcaster();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ class NullParameter implements IParameter {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
// nothing
|
// nothing
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
import ca.uhn.fhir.rest.annotation.Offset;
|
import ca.uhn.fhir.rest.annotation.Offset;
|
||||||
import ca.uhn.fhir.rest.annotation.Since;
|
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||||
|
@ -42,7 +41,7 @@ public class OffsetParameter implements IParameter {
|
||||||
private Class<?> myType;
|
private Class<?> myType;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
String[] sinceParams = theRequest.getParameters().get(Constants.PARAM_OFFSET);
|
String[] sinceParams = theRequest.getParameters().get(Constants.PARAM_OFFSET);
|
||||||
if (sinceParams != null) {
|
if (sinceParams != null) {
|
||||||
if (sinceParams.length > 0) {
|
if (sinceParams.length > 0) {
|
||||||
|
|
|
@ -251,7 +251,7 @@ public class OperationParameter implements IParameter {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
List<Object> matchingParamValues = new ArrayList<Object>();
|
List<Object> matchingParamValues = new ArrayList<Object>();
|
||||||
|
|
||||||
OperationMethodBinding method = (OperationMethodBinding) theMethodBinding;
|
OperationMethodBinding method = (OperationMethodBinding) theMethodBinding;
|
||||||
|
|
|
@ -35,7 +35,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
class PatchTypeParameter implements IParameter {
|
class PatchTypeParameter implements IParameter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return getTypeForRequestOrThrowInvalidRequestException(theRequest);
|
return getTypeForRequestOrThrowInvalidRequestException(theRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class RawParamsParameter implements IParameter {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
HashMap<String, List<String>> retVal = null;
|
HashMap<String, List<String>> retVal = null;
|
||||||
|
|
||||||
for (String nextName : theRequest.getParameters().keySet()) {
|
for (String nextName : theRequest.getParameters().keySet()) {
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Class<?>> getAllowableParamAnnotations() {
|
public List<Class<?>> getAllowableParamAnnotations() {
|
||||||
ArrayList<Class<?>> retVal = new ArrayList<Class<?>>();
|
ArrayList<Class<?>> retVal = new ArrayList<>();
|
||||||
retVal.add(IdParam.class);
|
retVal.add(IdParam.class);
|
||||||
retVal.add(Elements.class);
|
retVal.add(Elements.class);
|
||||||
return retVal;
|
return retVal;
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class RequestDetailsParameter implements IParameter {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return theRequest;
|
return theRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class ResourceParameter implements IParameter {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
switch (myMode) {
|
switch (myMode) {
|
||||||
case BODY:
|
case BODY:
|
||||||
try {
|
try {
|
||||||
|
@ -141,7 +141,7 @@ public class ResourceParameter implements IParameter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static <T extends IBaseResource> T loadResourceFromRequest(RequestDetails theRequest, @Nonnull BaseMethodBinding<?> theMethodBinding, Class<T> theResourceType) {
|
static <T extends IBaseResource> T loadResourceFromRequest(RequestDetails theRequest, @Nonnull BaseMethodBinding theMethodBinding, Class<T> theResourceType) {
|
||||||
FhirContext ctx = theRequest.getServer().getFhirContext();
|
FhirContext ctx = theRequest.getServer().getFhirContext();
|
||||||
|
|
||||||
final Charset charset = determineRequestCharset(theRequest);
|
final Charset charset = determineRequestCharset(theRequest);
|
||||||
|
@ -195,7 +195,7 @@ public class ResourceParameter implements IParameter {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IBaseResource parseResourceFromRequest(RequestDetails theRequest, @Nonnull BaseMethodBinding<?> theMethodBinding, Class<? extends IBaseResource> theResourceType) {
|
static IBaseResource parseResourceFromRequest(RequestDetails theRequest, @Nonnull BaseMethodBinding theMethodBinding, Class<? extends IBaseResource> theResourceType) {
|
||||||
if (theRequest.getResource() != null) {
|
if (theRequest.getResource() != null) {
|
||||||
return theRequest.getResource();
|
return theRequest.getResource();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
class SearchContainedModeParameter implements IParameter {
|
class SearchContainedModeParameter implements IParameter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return getTypeForRequestOrThrowInvalidRequestException(theRequest);
|
return getTypeForRequestOrThrowInvalidRequestException(theRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ import java.util.Collection;
|
||||||
class SearchTotalModeParameter implements IParameter {
|
class SearchTotalModeParameter implements IParameter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return getTypeForRequestOrThrowInvalidRequestException(theRequest);
|
return getTypeForRequestOrThrowInvalidRequestException(theRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
class ServerBaseParamBinder implements IParameter {
|
class ServerBaseParamBinder implements IParameter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return theRequest.getFhirServerBase();
|
return theRequest.getFhirServerBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ class ServletRequestParameter implements IParameter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return ((ServletRequestDetails) theRequest).getServletRequest();
|
return ((ServletRequestDetails) theRequest).getServletRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ class ServletResponseParameter implements IParameter {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServletResponseParameter.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServletResponseParameter.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
return ((ServletRequestDetails) theRequest).getServletResponse();
|
return ((ServletRequestDetails) theRequest).getServletResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class SortParameter implements IParameter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT)) {
|
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT)) {
|
||||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_ASC)) {
|
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_ASC)) {
|
||||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_DESC)) {
|
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_DESC)) {
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class SummaryEnumParameter implements IParameter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
Set<SummaryEnum> value = getSummaryValueOrNull(theRequest);
|
Set<SummaryEnum> value = getSummaryValueOrNull(theRequest);
|
||||||
if (value == null || value.isEmpty()) {
|
if (value == null || value.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class TransactionParameter implements IParameter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
IBaseResource parsedBundle = ResourceParameter.parseResourceFromRequest(theRequest, theMethodBinding, myResourceBundleType);
|
IBaseResource parsedBundle = ResourceParameter.parseResourceFromRequest(theRequest, theMethodBinding, myResourceBundleType);
|
||||||
|
|
||||||
switch (myParamStyle) {
|
switch (myParamStyle) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServerConfiguration;
|
import ca.uhn.fhir.rest.server.RestfulServerConfiguration;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.IParameter;
|
import ca.uhn.fhir.rest.server.method.IParameter;
|
||||||
import ca.uhn.fhir.rest.server.method.OperationMethodBinding;
|
import ca.uhn.fhir.rest.server.method.OperationMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.OperationMethodBinding.ReturnType;
|
import ca.uhn.fhir.rest.server.method.OperationMethodBinding.ReturnType;
|
||||||
|
@ -134,7 +135,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
myValidationSupport = theValidationSupport;
|
myValidationSupport = theValidationSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBindingForSystemOps(FhirTerser theTerser, IBase theRest, Set<String> theSystemOps, BaseMethodBinding<?> theMethodBinding) {
|
private void checkBindingForSystemOps(FhirTerser theTerser, IBase theRest, Set<String> theSystemOps, BaseMethodBinding theMethodBinding) {
|
||||||
RestOperationTypeEnum restOperationType = theMethodBinding.getRestOperationType();
|
RestOperationTypeEnum restOperationType = theMethodBinding.getRestOperationType();
|
||||||
if (restOperationType.isSystemLevel()) {
|
if (restOperationType.isSystemLevel()) {
|
||||||
String sysOp = restOperationType.getCode();
|
String sysOp = restOperationType.getCode();
|
||||||
|
@ -236,15 +237,15 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
|
|
||||||
Set<String> systemOps = new HashSet<>();
|
Set<String> systemOps = new HashSet<>();
|
||||||
|
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = configuration.collectMethodBindings();
|
Map<String, List<BaseMethodBinding>> resourceToMethods = configuration.collectMethodBindings();
|
||||||
Map<String, Class<? extends IBaseResource>> resourceNameToSharedSupertype = configuration.getNameToSharedSupertype();
|
Map<String, Class<? extends IBaseResource>> resourceNameToSharedSupertype = configuration.getNameToSharedSupertype();
|
||||||
List<BaseMethodBinding<?>> globalMethodBindings = configuration.getGlobalBindings();
|
List<BaseMethodBinding> globalMethodBindings = configuration.getGlobalBindings();
|
||||||
|
|
||||||
TreeMultimap<String, String> resourceNameToIncludes = TreeMultimap.create();
|
TreeMultimap<String, String> resourceNameToIncludes = TreeMultimap.create();
|
||||||
TreeMultimap<String, String> resourceNameToRevIncludes = TreeMultimap.create();
|
TreeMultimap<String, String> resourceNameToRevIncludes = TreeMultimap.create();
|
||||||
for (Entry<String, List<BaseMethodBinding<?>>> nextEntry : resourceToMethods.entrySet()) {
|
for (Entry<String, List<BaseMethodBinding>> nextEntry : resourceToMethods.entrySet()) {
|
||||||
String resourceName = nextEntry.getKey();
|
String resourceName = nextEntry.getKey();
|
||||||
for (BaseMethodBinding<?> nextMethod : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethod : nextEntry.getValue()) {
|
||||||
if (nextMethod instanceof SearchMethodBinding) {
|
if (nextMethod instanceof SearchMethodBinding) {
|
||||||
resourceNameToIncludes.putAll(resourceName, nextMethod.getIncludes());
|
resourceNameToIncludes.putAll(resourceName, nextMethod.getIncludes());
|
||||||
resourceNameToRevIncludes.putAll(resourceName, nextMethod.getRevIncludes());
|
resourceNameToRevIncludes.putAll(resourceName, nextMethod.getRevIncludes());
|
||||||
|
@ -253,7 +254,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Entry<String, List<BaseMethodBinding<?>>> nextEntry : resourceToMethods.entrySet()) {
|
for (Entry<String, List<BaseMethodBinding>> nextEntry : resourceToMethods.entrySet()) {
|
||||||
|
|
||||||
Set<String> operationNames = new HashSet<>();
|
Set<String> operationNames = new HashSet<>();
|
||||||
String resourceName = nextEntry.getKey();
|
String resourceName = nextEntry.getKey();
|
||||||
|
@ -273,7 +274,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
terser.addElement(resource, "type", def.getName());
|
terser.addElement(resource, "type", def.getName());
|
||||||
terser.addElement(resource, "profile", def.getResourceProfile(serverBase));
|
terser.addElement(resource, "profile", def.getResourceProfile(serverBase));
|
||||||
|
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
RestOperationTypeEnum resOpCode = nextMethodBinding.getRestOperationType();
|
RestOperationTypeEnum resOpCode = nextMethodBinding.getRestOperationType();
|
||||||
if (resOpCode.isTypeLevel() || resOpCode.isInstanceLevel()) {
|
if (resOpCode.isTypeLevel() || resOpCode.isInstanceLevel()) {
|
||||||
String resOp;
|
String resOp;
|
||||||
|
@ -358,7 +359,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
// global flag set to true, meaning they apply to all resource types)
|
// global flag set to true, meaning they apply to all resource types)
|
||||||
if (globalMethodBindings != null) {
|
if (globalMethodBindings != null) {
|
||||||
Set<String> globalOperationNames = new HashSet<>();
|
Set<String> globalOperationNames = new HashSet<>();
|
||||||
for (BaseMethodBinding<?> next : globalMethodBindings) {
|
for (BaseMethodBinding next : globalMethodBindings) {
|
||||||
if (next instanceof OperationMethodBinding) {
|
if (next instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) next;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) next;
|
||||||
if (methodBinding.isGlobalMethod()) {
|
if (methodBinding.isGlobalMethod()) {
|
||||||
|
@ -482,7 +483,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
checkBindingForSystemOps(terser, rest, systemOps, nextMethodBinding);
|
checkBindingForSystemOps(terser, rest, systemOps, nextMethodBinding);
|
||||||
if (nextMethodBinding instanceof OperationMethodBinding) {
|
if (nextMethodBinding instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
||||||
|
@ -507,7 +508,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
// global flag set to true, meaning they apply to all resource types)
|
// global flag set to true, meaning they apply to all resource types)
|
||||||
if (globalMethodBindings != null) {
|
if (globalMethodBindings != null) {
|
||||||
Set<String> globalOperationNames = new HashSet<>();
|
Set<String> globalOperationNames = new HashSet<>();
|
||||||
for (BaseMethodBinding<?> next : globalMethodBindings) {
|
for (BaseMethodBinding next : globalMethodBindings) {
|
||||||
if (next instanceof OperationMethodBinding) {
|
if (next instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) next;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) next;
|
||||||
if (methodBinding.isGlobalMethod()) {
|
if (methodBinding.isGlobalMethod()) {
|
||||||
|
|
|
@ -25,15 +25,15 @@ class ResourceBindingTest {
|
||||||
public void testFILO() throws NoSuchMethodException {
|
public void testFILO() throws NoSuchMethodException {
|
||||||
// setup
|
// setup
|
||||||
Method method = ResourceBindingTest.class.getMethod("testFILO");
|
Method method = ResourceBindingTest.class.getMethod("testFILO");
|
||||||
BaseMethodBinding<?> first = new PageMethodBinding(ourFhirContext, method);
|
BaseMethodBinding first = new PageMethodBinding(ourFhirContext, method);
|
||||||
BaseMethodBinding<?> second = new PageMethodBinding(ourFhirContext, method);;
|
BaseMethodBinding second = new PageMethodBinding(ourFhirContext, method);;
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
myResourceBinding.addMethod(first);
|
myResourceBinding.addMethod(first);
|
||||||
myResourceBinding.addMethod(second);
|
myResourceBinding.addMethod(second);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
List<BaseMethodBinding<?>> list = myResourceBinding.getMethodBindings();
|
List<BaseMethodBinding> list = myResourceBinding.getMethodBindings();
|
||||||
assertNotEquals(first, second);
|
assertNotEquals(first, second);
|
||||||
assertEquals(second, list.get(0));
|
assertEquals(second, list.get(0));
|
||||||
assertEquals(first, list.get(1));
|
assertEquals(first, list.get(1));
|
||||||
|
|
|
@ -32,9 +32,9 @@ import ca.uhn.fhir.batch2.jobs.export.models.BulkExportJobParameters;
|
||||||
import ca.uhn.fhir.batch2.model.ChunkOutcome;
|
import ca.uhn.fhir.batch2.model.ChunkOutcome;
|
||||||
import ca.uhn.fhir.batch2.model.JobInstance;
|
import ca.uhn.fhir.batch2.model.JobInstance;
|
||||||
import ca.uhn.fhir.jpa.api.model.BulkExportJobResults;
|
import ca.uhn.fhir.jpa.api.model.BulkExportJobResults;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -47,10 +47,10 @@ public class BulkExportCreateReportStep implements IReductionStepWorker<BulkExpo
|
||||||
|
|
||||||
private Map<String, List<String>> myResourceToBinaryIds;
|
private Map<String, List<String>> myResourceToBinaryIds;
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(@NotNull StepExecutionDetails<BulkExportJobParameters, BulkExportBinaryFileId> theStepExecutionDetails,
|
public RunOutcome run(@Nonnull StepExecutionDetails<BulkExportJobParameters, BulkExportBinaryFileId> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<BulkExportJobResults> theDataSink) throws JobExecutionFailedException {
|
@Nonnull IJobDataSink<BulkExportJobResults> theDataSink) throws JobExecutionFailedException {
|
||||||
BulkExportJobResults results = new BulkExportJobResults();
|
BulkExportJobResults results = new BulkExportJobResults();
|
||||||
|
|
||||||
String requestUrl = getOriginatingRequestUrl(theStepExecutionDetails, results);
|
String requestUrl = getOriginatingRequestUrl(theStepExecutionDetails, results);
|
||||||
|
@ -74,7 +74,7 @@ public class BulkExportCreateReportStep implements IReductionStepWorker<BulkExpo
|
||||||
return RunOutcome.SUCCESS;
|
return RunOutcome.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getOriginatingRequestUrl(@NotNull StepExecutionDetails<BulkExportJobParameters, BulkExportBinaryFileId> theStepExecutionDetails, BulkExportJobResults results) {
|
private static String getOriginatingRequestUrl(@Nonnull StepExecutionDetails<BulkExportJobParameters, BulkExportBinaryFileId> theStepExecutionDetails, BulkExportJobResults results) {
|
||||||
IJobInstance instance = theStepExecutionDetails.getInstance();
|
IJobInstance instance = theStepExecutionDetails.getInstance();
|
||||||
String url = "";
|
String url = "";
|
||||||
if (instance instanceof JobInstance) {
|
if (instance instanceof JobInstance) {
|
||||||
|
@ -86,7 +86,7 @@ public class BulkExportCreateReportStep implements IReductionStepWorker<BulkExpo
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public ChunkOutcome consume(ChunkExecutionDetails<BulkExportJobParameters,
|
public ChunkOutcome consume(ChunkExecutionDetails<BulkExportJobParameters,
|
||||||
BulkExportBinaryFileId> theChunkDetails) {
|
BulkExportBinaryFileId> theChunkDetails) {
|
||||||
|
|
|
@ -22,9 +22,9 @@ package ca.uhn.fhir.batch2.jobs.expunge;
|
||||||
|
|
||||||
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
|
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
|
||||||
import ca.uhn.fhir.batch2.jobs.parameters.UrlListValidator;
|
import ca.uhn.fhir.batch2.jobs.parameters.UrlListValidator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DeleteExpungeJobParametersValidator implements IJobParametersValidator<DeleteExpungeJobParameters> {
|
public class DeleteExpungeJobParametersValidator implements IJobParametersValidator<DeleteExpungeJobParameters> {
|
||||||
|
@ -36,7 +36,7 @@ public class DeleteExpungeJobParametersValidator implements IJobParametersValida
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public List<String> validate(@NotNull DeleteExpungeJobParameters theParameters) {
|
public List<String> validate(@Nonnull DeleteExpungeJobParameters theParameters) {
|
||||||
return myUrlListValidator.validatePartitionedUrls(theParameters.getPartitionedUrls());
|
return myUrlListValidator.validatePartitionedUrls(theParameters.getPartitionedUrls());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,11 @@ package ca.uhn.fhir.batch2.jobs.reindex;
|
||||||
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
|
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
|
||||||
import ca.uhn.fhir.batch2.jobs.parameters.PartitionedUrl;
|
import ca.uhn.fhir.batch2.jobs.parameters.PartitionedUrl;
|
||||||
import ca.uhn.fhir.batch2.jobs.parameters.UrlListValidator;
|
import ca.uhn.fhir.batch2.jobs.parameters.UrlListValidator;
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class ReindexJobParametersValidator implements IJobParametersValidator<ReindexJobParameters> {
|
public class ReindexJobParametersValidator implements IJobParametersValidator<ReindexJobParameters> {
|
||||||
|
|
||||||
|
@ -42,7 +39,7 @@ public class ReindexJobParametersValidator implements IJobParametersValidator<Re
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public List<String> validate(@NotNull ReindexJobParameters theParameters) {
|
public List<String> validate(@Nonnull ReindexJobParameters theParameters) {
|
||||||
List<String> errors = myUrlListValidator.validatePartitionedUrls(theParameters.getPartitionedUrls());
|
List<String> errors = myUrlListValidator.validatePartitionedUrls(theParameters.getPartitionedUrls());
|
||||||
|
|
||||||
if (errors == null || errors.isEmpty()) {
|
if (errors == null || errors.isEmpty()) {
|
||||||
|
|
|
@ -547,7 +547,7 @@ public abstract class BaseTransactionProcessor {
|
||||||
|
|
||||||
String url = requestDetails.getRequestPath();
|
String url = requestDetails.getRequestPath();
|
||||||
|
|
||||||
BaseMethodBinding<?> method = srd.getServer().determineResourceMethod(requestDetails, url);
|
BaseMethodBinding method = srd.getServer().determineResourceMethod(requestDetails, url);
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
throw new IllegalArgumentException(Msg.code(532) + "Unable to handle GET " + url);
|
throw new IllegalArgumentException(Msg.code(532) + "Unable to handle GET " + url);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
super(theServerConfiguration);
|
super(theServerConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBindingForSystemOps(ConformanceRestComponent rest, Set<SystemRestfulInteraction> systemOps, BaseMethodBinding<?> nextMethodBinding) {
|
private void checkBindingForSystemOps(ConformanceRestComponent rest, Set<SystemRestfulInteraction> systemOps, BaseMethodBinding nextMethodBinding) {
|
||||||
if (nextMethodBinding.getRestOperationType() != null) {
|
if (nextMethodBinding.getRestOperationType() != null) {
|
||||||
String sysOpCode = nextMethodBinding.getRestOperationType().getCode();
|
String sysOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||||
if (sysOpCode != null) {
|
if (sysOpCode != null) {
|
||||||
|
@ -110,18 +110,18 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, List<BaseMethodBinding<?>>> collectMethodBindings(RequestDetails theRequestDetails) {
|
private Map<String, List<BaseMethodBinding>> collectMethodBindings(RequestDetails theRequestDetails) {
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = new TreeMap<>();
|
Map<String, List<BaseMethodBinding>> resourceToMethods = new TreeMap<>();
|
||||||
for (ResourceBinding next : getServerConfiguration(theRequestDetails).getResourceBindings()) {
|
for (ResourceBinding next : getServerConfiguration(theRequestDetails).getResourceBindings()) {
|
||||||
String resourceName = next.getResourceName();
|
String resourceName = next.getResourceName();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : next.getMethodBindings()) {
|
for (BaseMethodBinding nextMethodBinding : next.getMethodBindings()) {
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<>());
|
resourceToMethods.put(resourceName, new ArrayList<>());
|
||||||
}
|
}
|
||||||
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : getServerConfiguration(theRequestDetails).getServerBindings()) {
|
for (BaseMethodBinding nextMethodBinding : getServerConfiguration(theRequestDetails).getServerBindings()) {
|
||||||
String resourceName = "";
|
String resourceName = "";
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<>());
|
resourceToMethods.put(resourceName, new ArrayList<>());
|
||||||
|
@ -208,8 +208,8 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
Set<SystemRestfulInteraction> systemOps = new HashSet<>();
|
Set<SystemRestfulInteraction> systemOps = new HashSet<>();
|
||||||
Set<String> operationNames = new HashSet<>();
|
Set<String> operationNames = new HashSet<>();
|
||||||
|
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = collectMethodBindings(theRequestDetails);
|
Map<String, List<BaseMethodBinding>> resourceToMethods = collectMethodBindings(theRequestDetails);
|
||||||
for (Entry<String, List<BaseMethodBinding<?>>> nextEntry : resourceToMethods.entrySet()) {
|
for (Entry<String, List<BaseMethodBinding>> nextEntry : resourceToMethods.entrySet()) {
|
||||||
|
|
||||||
if (nextEntry.getKey().isEmpty() == false) {
|
if (nextEntry.getKey().isEmpty() == false) {
|
||||||
Set<TypeRestfulInteraction> resourceOps = new HashSet<>();
|
Set<TypeRestfulInteraction> resourceOps = new HashSet<>();
|
||||||
|
@ -223,7 +223,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
|
|
||||||
// Map<String, Conformance.RestResourceSearchParam> nameToSearchParam = new HashMap<String,
|
// Map<String, Conformance.RestResourceSearchParam> nameToSearchParam = new HashMap<String,
|
||||||
// Conformance.RestResourceSearchParam>();
|
// Conformance.RestResourceSearchParam>();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
if (nextMethodBinding.getRestOperationType() != null) {
|
if (nextMethodBinding.getRestOperationType() != null) {
|
||||||
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||||
if (resOpCode != null) {
|
if (resOpCode != null) {
|
||||||
|
@ -307,7 +307,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
resource.addSearchInclude(nextInclude);
|
resource.addSearchInclude(nextInclude);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
checkBindingForSystemOps(rest, systemOps, nextMethodBinding);
|
checkBindingForSystemOps(rest, systemOps, nextMethodBinding);
|
||||||
if (nextMethodBinding instanceof OperationMethodBinding) {
|
if (nextMethodBinding instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
super(theServerConfiguration);
|
super(theServerConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBindingForSystemOps(Rest rest, Set<SystemRestfulInteractionEnum> systemOps, BaseMethodBinding<?> nextMethodBinding) {
|
private void checkBindingForSystemOps(Rest rest, Set<SystemRestfulInteractionEnum> systemOps, BaseMethodBinding nextMethodBinding) {
|
||||||
if (nextMethodBinding.getRestOperationType() != null) {
|
if (nextMethodBinding.getRestOperationType() != null) {
|
||||||
String sysOpCode = nextMethodBinding.getRestOperationType().getCode();
|
String sysOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||||
if (sysOpCode != null) {
|
if (sysOpCode != null) {
|
||||||
|
@ -105,21 +105,21 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, List<BaseMethodBinding<?>>> collectMethodBindings(RequestDetails theRequestDetails) {
|
private Map<String, List<BaseMethodBinding>> collectMethodBindings(RequestDetails theRequestDetails) {
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = new TreeMap<String, List<BaseMethodBinding<?>>>();
|
Map<String, List<BaseMethodBinding>> resourceToMethods = new TreeMap<String, List<BaseMethodBinding>>();
|
||||||
for (ResourceBinding next : getServerConfiguration(theRequestDetails).getResourceBindings()) {
|
for (ResourceBinding next : getServerConfiguration(theRequestDetails).getResourceBindings()) {
|
||||||
String resourceName = next.getResourceName();
|
String resourceName = next.getResourceName();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : next.getMethodBindings()) {
|
for (BaseMethodBinding nextMethodBinding : next.getMethodBindings()) {
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<BaseMethodBinding<?>>());
|
resourceToMethods.put(resourceName, new ArrayList<BaseMethodBinding>());
|
||||||
}
|
}
|
||||||
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : getServerConfiguration(theRequestDetails).getServerBindings()) {
|
for (BaseMethodBinding nextMethodBinding : getServerConfiguration(theRequestDetails).getServerBindings()) {
|
||||||
String resourceName = "";
|
String resourceName = "";
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<BaseMethodBinding<?>>());
|
resourceToMethods.put(resourceName, new ArrayList<BaseMethodBinding>());
|
||||||
}
|
}
|
||||||
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
||||||
}
|
}
|
||||||
|
@ -209,8 +209,8 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
Set<SystemRestfulInteractionEnum> systemOps = new HashSet<>();
|
Set<SystemRestfulInteractionEnum> systemOps = new HashSet<>();
|
||||||
Set<String> operationNames = new HashSet<>();
|
Set<String> operationNames = new HashSet<>();
|
||||||
|
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = collectMethodBindings(theRequestDetails);
|
Map<String, List<BaseMethodBinding>> resourceToMethods = collectMethodBindings(theRequestDetails);
|
||||||
for (Entry<String, List<BaseMethodBinding<?>>> nextEntry : resourceToMethods.entrySet()) {
|
for (Entry<String, List<BaseMethodBinding>> nextEntry : resourceToMethods.entrySet()) {
|
||||||
|
|
||||||
if (nextEntry.getKey().isEmpty() == false) {
|
if (nextEntry.getKey().isEmpty() == false) {
|
||||||
Set<TypeRestfulInteractionEnum> resourceOps = new HashSet<>();
|
Set<TypeRestfulInteractionEnum> resourceOps = new HashSet<>();
|
||||||
|
@ -224,7 +224,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
|
|
||||||
// Map<String, Conformance.RestResourceSearchParam> nameToSearchParam = new HashMap<String,
|
// Map<String, Conformance.RestResourceSearchParam> nameToSearchParam = new HashMap<String,
|
||||||
// Conformance.RestResourceSearchParam>();
|
// Conformance.RestResourceSearchParam>();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
if (nextMethodBinding.getRestOperationType() != null) {
|
if (nextMethodBinding.getRestOperationType() != null) {
|
||||||
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||||
if (resOpCode != null) {
|
if (resOpCode != null) {
|
||||||
|
@ -303,7 +303,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
resource.addSearchInclude(nextInclude);
|
resource.addSearchInclude(nextInclude);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
checkBindingForSystemOps(rest, systemOps, nextMethodBinding);
|
checkBindingForSystemOps(rest, systemOps, nextMethodBinding);
|
||||||
if (nextMethodBinding instanceof OperationMethodBinding) {
|
if (nextMethodBinding instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
||||||
|
|
|
@ -229,7 +229,7 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||||
assertEquals("The patient's identifier", param.getDescription());
|
assertEquals("The patient's identifier", param.getDescription());
|
||||||
|
@ -459,7 +459,7 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
for (IParameter next : binding.getParameters()) {
|
for (IParameter next : binding.getParameters()) {
|
||||||
SearchParameter param = (SearchParameter) next;
|
SearchParameter param = (SearchParameter) next;
|
||||||
|
@ -499,7 +499,7 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(24);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(24);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
@ -533,7 +533,7 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
@ -569,7 +569,7 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
||||||
super(theServerConfiguration);
|
super(theServerConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBindingForSystemOps(CapabilityStatementRestComponent rest, Set<SystemRestfulInteraction> systemOps, BaseMethodBinding<?> nextMethodBinding) {
|
private void checkBindingForSystemOps(CapabilityStatementRestComponent rest, Set<SystemRestfulInteraction> systemOps, BaseMethodBinding nextMethodBinding) {
|
||||||
if (nextMethodBinding.getRestOperationType() != null) {
|
if (nextMethodBinding.getRestOperationType() != null) {
|
||||||
String sysOpCode = nextMethodBinding.getRestOperationType().getCode();
|
String sysOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||||
if (sysOpCode != null) {
|
if (sysOpCode != null) {
|
||||||
|
@ -115,18 +115,18 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, List<BaseMethodBinding<?>>> collectMethodBindings(RequestDetails theRequestDetails) {
|
private Map<String, List<BaseMethodBinding>> collectMethodBindings(RequestDetails theRequestDetails) {
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = new TreeMap<>();
|
Map<String, List<BaseMethodBinding>> resourceToMethods = new TreeMap<>();
|
||||||
for (ResourceBinding next : getServerConfiguration(theRequestDetails).getResourceBindings()) {
|
for (ResourceBinding next : getServerConfiguration(theRequestDetails).getResourceBindings()) {
|
||||||
String resourceName = next.getResourceName();
|
String resourceName = next.getResourceName();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : next.getMethodBindings()) {
|
for (BaseMethodBinding nextMethodBinding : next.getMethodBindings()) {
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<>());
|
resourceToMethods.put(resourceName, new ArrayList<>());
|
||||||
}
|
}
|
||||||
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : getServerConfiguration(theRequestDetails).getServerBindings()) {
|
for (BaseMethodBinding nextMethodBinding : getServerConfiguration(theRequestDetails).getServerBindings()) {
|
||||||
String resourceName = "";
|
String resourceName = "";
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<>());
|
resourceToMethods.put(resourceName, new ArrayList<>());
|
||||||
|
@ -235,9 +235,9 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
||||||
Set<SystemRestfulInteraction> systemOps = new HashSet<>();
|
Set<SystemRestfulInteraction> systemOps = new HashSet<>();
|
||||||
Set<String> operationNames = new HashSet<>();
|
Set<String> operationNames = new HashSet<>();
|
||||||
|
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = collectMethodBindings(theRequestDetails);
|
Map<String, List<BaseMethodBinding>> resourceToMethods = collectMethodBindings(theRequestDetails);
|
||||||
Map<String, Class<? extends IBaseResource>> resourceNameToSharedSupertype = serverConfiguration.getNameToSharedSupertype();
|
Map<String, Class<? extends IBaseResource>> resourceNameToSharedSupertype = serverConfiguration.getNameToSharedSupertype();
|
||||||
for (Entry<String, List<BaseMethodBinding<?>>> nextEntry : resourceToMethods.entrySet()) {
|
for (Entry<String, List<BaseMethodBinding>> nextEntry : resourceToMethods.entrySet()) {
|
||||||
|
|
||||||
if (nextEntry.getKey().isEmpty() == false) {
|
if (nextEntry.getKey().isEmpty() == false) {
|
||||||
Set<TypeRestfulInteraction> resourceOps = new HashSet<>();
|
Set<TypeRestfulInteraction> resourceOps = new HashSet<>();
|
||||||
|
@ -258,7 +258,7 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
||||||
|
|
||||||
// Map<String, CapabilityStatement.RestResourceSearchParam> nameToSearchParam = new HashMap<String,
|
// Map<String, CapabilityStatement.RestResourceSearchParam> nameToSearchParam = new HashMap<String,
|
||||||
// CapabilityStatement.RestResourceSearchParam>();
|
// CapabilityStatement.RestResourceSearchParam>();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
if (nextMethodBinding.getRestOperationType() != null) {
|
if (nextMethodBinding.getRestOperationType() != null) {
|
||||||
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||||
if (resOpCode != null) {
|
if (resOpCode != null) {
|
||||||
|
@ -350,7 +350,7 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
||||||
resource.addSearchInclude(nextInclude);
|
resource.addSearchInclude(nextInclude);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
checkBindingForSystemOps(rest, systemOps, nextMethodBinding);
|
checkBindingForSystemOps(rest, systemOps, nextMethodBinding);
|
||||||
if (nextMethodBinding instanceof OperationMethodBinding) {
|
if (nextMethodBinding instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
||||||
|
|
|
@ -74,7 +74,6 @@ import org.junit.jupiter.api.Test;
|
||||||
import javax.servlet.ServletConfig;
|
import javax.servlet.ServletConfig;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.tools.Diagnostic;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -153,7 +152,7 @@ public class ServerCapabilityStatementProviderDstu3Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
@ -304,7 +303,7 @@ public class ServerCapabilityStatementProviderDstu3Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||||
assertEquals("The patient's identifier", param.getDescription());
|
assertEquals("The patient's identifier", param.getDescription());
|
||||||
|
@ -521,7 +520,7 @@ public class ServerCapabilityStatementProviderDstu3Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
for (IParameter next : binding.getParameters()) {
|
for (IParameter next : binding.getParameters()) {
|
||||||
SearchParameter param = (SearchParameter) next;
|
SearchParameter param = (SearchParameter) next;
|
||||||
|
@ -561,7 +560,7 @@ public class ServerCapabilityStatementProviderDstu3Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(25);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(25);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
@ -594,7 +593,7 @@ public class ServerCapabilityStatementProviderDstu3Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
|
|
@ -111,7 +111,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBindingForSystemOps(ConformanceRestComponent rest, Set<SystemRestfulInteraction> systemOps,
|
private void checkBindingForSystemOps(ConformanceRestComponent rest, Set<SystemRestfulInteraction> systemOps,
|
||||||
BaseMethodBinding<?> nextMethodBinding) {
|
BaseMethodBinding nextMethodBinding) {
|
||||||
if (nextMethodBinding.getRestOperationType() != null) {
|
if (nextMethodBinding.getRestOperationType() != null) {
|
||||||
String sysOpCode = nextMethodBinding.getRestOperationType().getCode();
|
String sysOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||||
if (sysOpCode != null) {
|
if (sysOpCode != null) {
|
||||||
|
@ -132,18 +132,18 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, List<BaseMethodBinding<?>>> collectMethodBindings(RequestDetails theRequestDetails) {
|
private Map<String, List<BaseMethodBinding>> collectMethodBindings(RequestDetails theRequestDetails) {
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = new TreeMap<String, List<BaseMethodBinding<?>>>();
|
Map<String, List<BaseMethodBinding>> resourceToMethods = new TreeMap<String, List<BaseMethodBinding>>();
|
||||||
for (ResourceBinding next : getServerConfiguration(theRequestDetails).getResourceBindings()) {
|
for (ResourceBinding next : getServerConfiguration(theRequestDetails).getResourceBindings()) {
|
||||||
String resourceName = next.getResourceName();
|
String resourceName = next.getResourceName();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : next.getMethodBindings()) {
|
for (BaseMethodBinding nextMethodBinding : next.getMethodBindings()) {
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<BaseMethodBinding<?>>());
|
resourceToMethods.put(resourceName, new ArrayList<BaseMethodBinding>());
|
||||||
}
|
}
|
||||||
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : getServerConfiguration(theRequestDetails).getServerBindings()) {
|
for (BaseMethodBinding nextMethodBinding : getServerConfiguration(theRequestDetails).getServerBindings()) {
|
||||||
String resourceName = "";
|
String resourceName = "";
|
||||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||||
resourceToMethods.put(resourceName, new ArrayList<>());
|
resourceToMethods.put(resourceName, new ArrayList<>());
|
||||||
|
@ -196,8 +196,8 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
Set<SystemRestfulInteraction> systemOps = new HashSet<>();
|
Set<SystemRestfulInteraction> systemOps = new HashSet<>();
|
||||||
Set<String> operationNames = new HashSet<>();
|
Set<String> operationNames = new HashSet<>();
|
||||||
|
|
||||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = collectMethodBindings(theRequestDetails);
|
Map<String, List<BaseMethodBinding>> resourceToMethods = collectMethodBindings(theRequestDetails);
|
||||||
for (Entry<String, List<BaseMethodBinding<?>>> nextEntry : resourceToMethods.entrySet()) {
|
for (Entry<String, List<BaseMethodBinding>> nextEntry : resourceToMethods.entrySet()) {
|
||||||
|
|
||||||
if (nextEntry.getKey().isEmpty() == false) {
|
if (nextEntry.getKey().isEmpty() == false) {
|
||||||
Set<TypeRestfulInteraction> resourceOps = new HashSet<>();
|
Set<TypeRestfulInteraction> resourceOps = new HashSet<>();
|
||||||
|
@ -214,7 +214,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
// Map<String, Conformance.RestResourceSearchParam> nameToSearchParam =
|
// Map<String, Conformance.RestResourceSearchParam> nameToSearchParam =
|
||||||
// new HashMap<String,
|
// new HashMap<String,
|
||||||
// Conformance.RestResourceSearchParam>();
|
// Conformance.RestResourceSearchParam>();
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
if (nextMethodBinding.getRestOperationType() != null) {
|
if (nextMethodBinding.getRestOperationType() != null) {
|
||||||
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||||
if (resOpCode != null) {
|
if (resOpCode != null) {
|
||||||
|
@ -296,7 +296,7 @@ public class ServerConformanceProvider extends BaseServerCapabilityStatementProv
|
||||||
resource.addSearchInclude(nextInclude);
|
resource.addSearchInclude(nextInclude);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
for (BaseMethodBinding nextMethodBinding : nextEntry.getValue()) {
|
||||||
checkBindingForSystemOps(rest, systemOps, nextMethodBinding);
|
checkBindingForSystemOps(rest, systemOps, nextMethodBinding);
|
||||||
if (nextMethodBinding instanceof OperationMethodBinding) {
|
if (nextMethodBinding instanceof OperationMethodBinding) {
|
||||||
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
OperationMethodBinding methodBinding = (OperationMethodBinding) nextMethodBinding;
|
||||||
|
|
|
@ -169,7 +169,7 @@ public class ServerConformanceProviderHl7OrgDstu2Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||||
assertEquals("The patient's identifier", param.getDescription());
|
assertEquals("The patient's identifier", param.getDescription());
|
||||||
|
@ -225,7 +225,7 @@ public class ServerConformanceProviderHl7OrgDstu2Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||||
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription());
|
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription());
|
||||||
|
@ -328,7 +328,7 @@ public class ServerConformanceProviderHl7OrgDstu2Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||||
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription());
|
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription());
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
|
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider;
|
||||||
|
import ca.uhn.fhir.test.utilities.ITestDataBuilder;
|
||||||
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.CapabilityStatement;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
|
import org.hl7.fhir.r4.model.Observation;
|
||||||
|
import org.hl7.fhir.r4.model.Organization;
|
||||||
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
public class InteractionBlockingInterceptorTest implements ITestDataBuilder {
|
||||||
|
public static final String SERVER_OP = "$server-op";
|
||||||
|
public static final String TYPE_OP = "$type-op";
|
||||||
|
public static final String INSTANCE_OP = "$instance-op";
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(InteractionBlockingInterceptorTest.class);
|
||||||
|
@RegisterExtension
|
||||||
|
private final RestfulServerExtension myServer = new RestfulServerExtension(ourCtx);
|
||||||
|
private final HashMapResourceProvider<Patient> myPatientProvider = new HashMapResourceProvider<>(ourCtx, Patient.class);
|
||||||
|
private final HashMapResourceProvider<Observation> myObservationProvider = new HashMapResourceProvider<>(ourCtx, Observation.class);
|
||||||
|
private final HashMapResourceProvider<Organization> myOrganizationProvider = new HashMapResourceProvider<>(ourCtx, Organization.class);
|
||||||
|
private InteractionBlockingInterceptor mySvc;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllowInteractions() {
|
||||||
|
// Setup
|
||||||
|
mySvc = new InteractionBlockingInterceptor.Builder(ourCtx)
|
||||||
|
.addAllowedSpec("Patient:read")
|
||||||
|
.addAllowedSpec("Observation:read")
|
||||||
|
.addAllowedSpec("Observation:create")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Test
|
||||||
|
registerProviders();
|
||||||
|
|
||||||
|
// Verify CapabilityStatement
|
||||||
|
Set<String> supportedOps = fetchCapabilityInteractions();
|
||||||
|
assertThat(supportedOps.toString(), supportedOps, containsInAnyOrder(
|
||||||
|
"Observation:create",
|
||||||
|
"Observation:read",
|
||||||
|
"Observation:vread",
|
||||||
|
"OperationDefinition:read",
|
||||||
|
"Patient:read",
|
||||||
|
"Patient:vread"
|
||||||
|
));
|
||||||
|
|
||||||
|
// Verify Server
|
||||||
|
verifyCreateObservationOk();
|
||||||
|
verifyReadObservationOk();
|
||||||
|
verifyReadEncounterFails();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllowOperations() {
|
||||||
|
// Setup
|
||||||
|
mySvc = new InteractionBlockingInterceptor.Builder(ourCtx)
|
||||||
|
.addAllowedSpec(SERVER_OP)
|
||||||
|
.addAllowedSpec(TYPE_OP)
|
||||||
|
.addAllowedSpec(INSTANCE_OP)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Test
|
||||||
|
registerProviders();
|
||||||
|
|
||||||
|
// Verify CapabilityStatement
|
||||||
|
Set<String> supportedOps = fetchCapabilityInteractions();
|
||||||
|
assertThat(supportedOps.toString(), supportedOps, containsInAnyOrder(
|
||||||
|
"OperationDefinition:read",
|
||||||
|
"Patient:$instance-op",
|
||||||
|
"Patient:$type-op",
|
||||||
|
"server:$server-op"
|
||||||
|
));
|
||||||
|
|
||||||
|
// Verify Server
|
||||||
|
verifyCreateObservationFails();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void verifyReadEncounterFails() {
|
||||||
|
try {
|
||||||
|
myServer.getFhirClient().read().resource("Encounter").withId("E0").execute();
|
||||||
|
fail();
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("Unknown resource type"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyReadObservationOk() {
|
||||||
|
myServer.getFhirClient().read().resource("Observation").withId("O0").execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyCreateObservationOk() {
|
||||||
|
myServer.getFhirClient().create().resource(new Observation()).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyCreateObservationFails() {
|
||||||
|
try {
|
||||||
|
myServer.getFhirClient().create().resource(new Observation()).execute();
|
||||||
|
fail();
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("Unknown resource type"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerProviders() {
|
||||||
|
createPatient(withId("P0"), withActiveTrue());
|
||||||
|
createObservation(withId("O0"), withStatus("final"));
|
||||||
|
createOrganization(withId("O0"), withName("An Organization"));
|
||||||
|
myServer.registerInterceptor(mySvc);
|
||||||
|
myServer.registerProvider(myPatientProvider);
|
||||||
|
myServer.registerProvider(myObservationProvider);
|
||||||
|
myServer.registerProvider(myOrganizationProvider);
|
||||||
|
myServer.registerProvider(new DummyOperationProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private Set<String> fetchCapabilityInteractions() {
|
||||||
|
CapabilityStatement cs = myServer.getFhirClient().capabilities().ofType(CapabilityStatement.class).execute();
|
||||||
|
TreeSet<String> supportedOps = new TreeSet<>();
|
||||||
|
// Type level
|
||||||
|
for (var nextResource : cs.getRestFirstRep().getResource()) {
|
||||||
|
for (var nextOp : nextResource.getInteraction()) {
|
||||||
|
supportedOps.add(nextResource.getType() + ":" + nextOp.getCode().toCode());
|
||||||
|
}
|
||||||
|
for (var nextOp : nextResource.getOperation()) {
|
||||||
|
supportedOps.add(nextResource.getType() + ":$" + nextOp.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Server level
|
||||||
|
for (var nextOp : cs.getRestFirstRep().getInteraction()) {
|
||||||
|
supportedOps.add("server:" + nextOp.getCode().toCode());
|
||||||
|
}
|
||||||
|
for (var nextOp : cs.getRestFirstRep().getOperation()) {
|
||||||
|
supportedOps.add("server:$" + nextOp.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(cs));
|
||||||
|
return supportedOps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType doCreateResource(IBaseResource theResource) {
|
||||||
|
if (theResource instanceof Patient) {
|
||||||
|
return myPatientProvider.store((Patient) theResource);
|
||||||
|
} else if (theResource instanceof Observation) {
|
||||||
|
return myObservationProvider.store((Observation) theResource);
|
||||||
|
} else if (theResource instanceof Organization) {
|
||||||
|
return myOrganizationProvider.store((Organization) theResource);
|
||||||
|
}
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType doUpdateResource(IBaseResource theResource) {
|
||||||
|
return doCreateResource(theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FhirContext getFhirContext() {
|
||||||
|
return ourCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static class DummyOperationProvider {
|
||||||
|
|
||||||
|
@Operation(name = SERVER_OP)
|
||||||
|
public Parameters serverOp(@ResourceParam Parameters theParameters) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(name = TYPE_OP, typeName = "Patient")
|
||||||
|
public Parameters typeOp(@ResourceParam Parameters theParameters) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(name = INSTANCE_OP, typeName = "Patient")
|
||||||
|
public Parameters serverOp(@IdParam IdType theId, @ResourceParam Parameters theParameters) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -259,7 +259,7 @@ public class ServerCapabilityStatementProviderR5Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||||
assertEquals("The patient's identifier", param.getDescription());
|
assertEquals("The patient's identifier", param.getDescription());
|
||||||
|
@ -459,7 +459,7 @@ public class ServerCapabilityStatementProviderR5Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
for (IParameter next : binding.getParameters()) {
|
for (IParameter next : binding.getParameters()) {
|
||||||
SearchParameter param = (SearchParameter) next;
|
SearchParameter param = (SearchParameter) next;
|
||||||
|
@ -499,7 +499,7 @@ public class ServerCapabilityStatementProviderR5Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(25);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(25);
|
||||||
assertEquals("careprovider", param.getName());
|
assertEquals("careprovider", param.getName());
|
||||||
|
@ -533,7 +533,7 @@ public class ServerCapabilityStatementProviderR5Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
|
|
@ -303,7 +303,7 @@ public class ServerCapabilityStatementProviderR4Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||||
assertEquals("The patient's identifier", param.getDescription());
|
assertEquals("The patient's identifier", param.getDescription());
|
||||||
|
@ -537,7 +537,7 @@ public class ServerCapabilityStatementProviderR4Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
for (IParameter next : binding.getParameters()) {
|
for (IParameter next : binding.getParameters()) {
|
||||||
SearchParameter param = (SearchParameter) next;
|
SearchParameter param = (SearchParameter) next;
|
||||||
|
@ -595,7 +595,7 @@ public class ServerCapabilityStatementProviderR4Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(25);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(25);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
@ -627,7 +627,7 @@ public class ServerCapabilityStatementProviderR4Test {
|
||||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
List<BaseMethodBinding> methodBindings = resourceBinding.getMethodBindings();
|
||||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||||
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
SearchParameter param = (SearchParameter) binding.getParameters().get(0);
|
||||||
assertEquals("The organization at which this person is a patient", param.getDescription());
|
assertEquals("The organization at which this person is a patient", param.getDescription());
|
||||||
|
|
|
@ -12,11 +12,11 @@ import org.hl7.fhir.common.hapi.validation.support.SnapshotGeneratingValidationS
|
||||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public class NpmPackageValidationSupportTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
private NpmPackageValidationSupport getNpmPackageValidationSupport(String theClasspath) throws IOException {
|
private NpmPackageValidationSupport getNpmPackageValidationSupport(String theClasspath) throws IOException {
|
||||||
NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(myFhirContext);
|
NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(myFhirContext);
|
||||||
npmPackageSupport.loadPackageFromClasspath(theClasspath);
|
npmPackageSupport.loadPackageFromClasspath(theClasspath);
|
||||||
|
|
|
@ -13,9 +13,9 @@ import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||||
import org.hl7.fhir.r4.model.IntegerType;
|
import org.hl7.fhir.r4.model.IntegerType;
|
||||||
import org.hl7.fhir.r4.model.MedicationRequest;
|
import org.hl7.fhir.r4.model.MedicationRequest;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@ -63,12 +63,12 @@ public class XverExtensionsValidationTest {
|
||||||
assertEquals("Extension_EXT_Type", errorMessage.getMessageId());
|
assertEquals("Extension_EXT_Type", errorMessage.getMessageId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
private static Predicate<SingleValidationMessage> errorMessagePredicate() {
|
private static Predicate<SingleValidationMessage> errorMessagePredicate() {
|
||||||
return message -> message.getSeverity() == ResultSeverityEnum.ERROR;
|
return message -> message.getSeverity() == ResultSeverityEnum.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
private static FhirValidator getFhirValidator() {
|
private static FhirValidator getFhirValidator() {
|
||||||
FhirValidator validator;
|
FhirValidator validator;
|
||||||
final FhirInstanceValidator instanceValidator = new FhirInstanceValidator(ourCtx);
|
final FhirInstanceValidator instanceValidator = new FhirInstanceValidator(ourCtx);
|
||||||
|
@ -79,14 +79,14 @@ public class XverExtensionsValidationTest {
|
||||||
return validator;
|
return validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
private static MedicationRequest getMedicationRequest() {
|
private static MedicationRequest getMedicationRequest() {
|
||||||
MedicationRequest med_req;
|
MedicationRequest med_req;
|
||||||
med_req = ourCtx.newJsonParser().parseResource(MedicationRequest.class, loadResource("/r4/amz/medication-request-amz.json"));
|
med_req = ourCtx.newJsonParser().parseResource(MedicationRequest.class, loadResource("/r4/amz/medication-request-amz.json"));
|
||||||
return med_req;
|
return med_req;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
private IValidationSupport getValidationSupport() throws IOException {
|
private IValidationSupport getValidationSupport() throws IOException {
|
||||||
NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(ourCtx);
|
NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(ourCtx);
|
||||||
npmPackageSupport.loadPackageFromClasspath("classpath:package/hl7.fhir.xver-extensions-0.0.11.tgz");
|
npmPackageSupport.loadPackageFromClasspath("classpath:package/hl7.fhir.xver-extensions-0.0.11.tgz");
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -1436,7 +1436,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.woodstox</groupId>
|
<groupId>com.fasterxml.woodstox</groupId>
|
||||||
<artifactId>woodstox-core</artifactId>
|
<artifactId>woodstox-core</artifactId>
|
||||||
<version>6.2.5</version>
|
<version>6.3.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.ebaysf.web</groupId>
|
<groupId>org.ebaysf.web</groupId>
|
||||||
|
|
Loading…
Reference in New Issue