Skip to content

Commit

Permalink
feat: implement search by resource operation in FHIR component in ord…
Browse files Browse the repository at this point in the history
…er transmit sensitive search parameters in request body
  • Loading branch information
cjmamo authored and davsclaus committed Oct 1, 2024
1 parent 1c76cdd commit 75fb269
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
*/
package org.apache.camel.component.fhir.api;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import ca.uhn.fhir.rest.api.SearchStyleEnum;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.gclient.IQuery;
import org.hl7.fhir.instance.model.api.IBaseBundle;
Expand Down Expand Up @@ -51,4 +54,25 @@ public IBaseBundle searchByUrl(String url, Map<ExtraParameters, Object> extraPar
return query.execute();
}

/**
* Perform a search by resource name.
*
* @param resourceName The resource to search for.
* @param searchParameters A set of search parameters to the query.
* @param searchStyle Forces the query to perform the search using the given method (allowable methods are
* described in the <a href="http://www.hl7.org/fhir/search.html">FHIR Search
* Specification</a>). The default search style is HTTP POST.
* @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be
* NULL
* @return the {@link IBaseBundle}
*/
public IBaseBundle searchByResource(
String resourceName, Map<String, List<String>> searchParameters, SearchStyleEnum searchStyle,
Map<ExtraParameters, Object> extraParameters) {
IQuery<IBaseBundle> query = client.search().forResource(resourceName);
query.whereMap(Objects.requireNonNullElse(searchParameters, Map.of()));
query.usingStyle(Objects.requireNonNullElse(searchStyle, SearchStyleEnum.POST));
ExtraParameters.process(extraParameters, query);
return query.execute();
}
}
2 changes: 2 additions & 0 deletions components/camel-fhir/camel-fhir-component/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@
<proxyClass>org.apache.camel.component.fhir.api.FhirSearch</proxyClass>
<fromJavasource />
<nullableOptions>
<nullableOption>searchParameters</nullableOption>
<nullableOption>searchStyle</nullableOption>
<nullableOption>extraParameters</nullableOption>
</nullableOptions>
</api>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class FhirEndpointUriFactory extends org.apache.camel.support.component.E
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
Set<String> props = new HashSet<>(81);
Set<String> props = new HashSet<>(84);
props.add("accessToken");
props.add("apiName");
props.add("asynchronous");
Expand Down Expand Up @@ -77,6 +77,7 @@ public class FhirEndpointUriFactory extends org.apache.camel.support.component.E
props.add("resource");
props.add("resourceAsString");
props.add("resourceClass");
props.add("resourceName");
props.add("resourceType");
props.add("resources");
props.add("respondToUri");
Expand All @@ -88,6 +89,8 @@ public class FhirEndpointUriFactory extends org.apache.camel.support.component.E
props.add("scheduledExecutorService");
props.add("scheduler");
props.add("schedulerProperties");
props.add("searchParameters");
props.add("searchStyle");
props.add("sendEmptyMessageWhenIdle");
props.add("serverUrl");
props.add("sessionCookie");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,23 @@
*/
@ApiParams(apiName = "search",
description = "API to search for resources matching a given set of criteria",
apiMethods = {@ApiMethod(methodName = "searchByUrl", description="Perform a search directly by URL", signatures={"org.hl7.fhir.instance.model.api.IBaseBundle searchByUrl(String url, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters, Object> extraParameters)"})}, aliases = {})
apiMethods = {@ApiMethod(methodName = "searchByResource", description="Perform a search by resource name", signatures={"org.hl7.fhir.instance.model.api.IBaseBundle searchByResource(String resourceName, java.util.Map<String, java.util.List<String>> searchParameters, ca.uhn.fhir.rest.api.SearchStyleEnum searchStyle, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters, Object> extraParameters)"}), @ApiMethod(methodName = "searchByUrl", description="Perform a search directly by URL", signatures={"org.hl7.fhir.instance.model.api.IBaseBundle searchByUrl(String url, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters, Object> extraParameters)"})}, aliases = {})
@UriParams
@Configurer(extended = true)
public final class FhirSearchEndpointConfiguration extends FhirConfiguration {
@UriParam
@ApiParam(optional = true, apiMethods = {@ApiMethod(methodName = "searchByUrl", description="See ExtraParameters for a full list of parameters that can be passed, may be NULL")})
@ApiParam(optional = true, apiMethods = {@ApiMethod(methodName = "searchByResource", description="See ExtraParameters for a full list of parameters that can be passed, may be NULL"), @ApiMethod(methodName = "searchByUrl", description="See ExtraParameters for a full list of parameters that can be passed, may be NULL")})
private java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters, Object> extraParameters;
@UriParam
@ApiParam(optional = false, apiMethods = {@ApiMethod(methodName = "searchByResource", description="The resource to search for")})
private String resourceName;
@UriParam
@ApiParam(optional = true, apiMethods = {@ApiMethod(methodName = "searchByResource", description="A set of search parameters to the query")})
private java.util.Map<String, java.util.List<String>> searchParameters;
@UriParam
@ApiParam(optional = true, apiMethods = {@ApiMethod(methodName = "searchByResource", description="Forces the query to perform the search using the given method (allowable methods are described in the FHIR Search Specification). The default search style is HTTP POST.")})
private ca.uhn.fhir.rest.api.SearchStyleEnum searchStyle;
@UriParam
@ApiParam(optional = false, apiMethods = {@ApiMethod(methodName = "searchByUrl", description="The URL to search for. Note that this URL may be complete (e.g. http://example.com/base/Patientname=foo) in which case the client's base URL will be ignored. Or it can be relative (e.g. Patientname=foo) in which case the client's base URL will be used.")})
private String url;

Expand All @@ -34,6 +43,30 @@ public void setExtraParameters(java.util.Map<org.apache.camel.component.fhir.api
this.extraParameters = extraParameters;
}

public String getResourceName() {
return resourceName;
}

public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}

public java.util.Map<String, java.util.List<String>> getSearchParameters() {
return searchParameters;
}

public void setSearchParameters(java.util.Map<String, java.util.List<String>> searchParameters) {
this.searchParameters = searchParameters;
}

public ca.uhn.fhir.rest.api.SearchStyleEnum getSearchStyle() {
return searchStyle;
}

public void setSearchStyle(ca.uhn.fhir.rest.api.SearchStyleEnum searchStyle) {
this.searchStyle = searchStyle;
}

public String getUrl() {
return url;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public class FhirSearchEndpointConfigurationConfigurer extends org.apache.camel.
map.put("ProxyPassword", java.lang.String.class);
map.put("ProxyPort", java.lang.Integer.class);
map.put("ProxyUser", java.lang.String.class);
map.put("ResourceName", java.lang.String.class);
map.put("SearchParameters", java.util.Map.class);
map.put("SearchStyle", ca.uhn.fhir.rest.api.SearchStyleEnum.class);
map.put("ServerUrl", java.lang.String.class);
map.put("SessionCookie", java.lang.String.class);
map.put("SocketTimeout", java.lang.Integer.class);
Expand Down Expand Up @@ -91,6 +94,12 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "proxyPort": target.setProxyPort(property(camelContext, java.lang.Integer.class, value)); return true;
case "proxyuser":
case "proxyUser": target.setProxyUser(property(camelContext, java.lang.String.class, value)); return true;
case "resourcename":
case "resourceName": target.setResourceName(property(camelContext, java.lang.String.class, value)); return true;
case "searchparameters":
case "searchParameters": target.setSearchParameters(property(camelContext, java.util.Map.class, value)); return true;
case "searchstyle":
case "searchStyle": target.setSearchStyle(property(camelContext, ca.uhn.fhir.rest.api.SearchStyleEnum.class, value)); return true;
case "serverurl":
case "serverUrl": target.setServerUrl(property(camelContext, java.lang.String.class, value)); return true;
case "sessioncookie":
Expand Down Expand Up @@ -149,6 +158,12 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "proxyPort": return java.lang.Integer.class;
case "proxyuser":
case "proxyUser": return java.lang.String.class;
case "resourcename":
case "resourceName": return java.lang.String.class;
case "searchparameters":
case "searchParameters": return java.util.Map.class;
case "searchstyle":
case "searchStyle": return ca.uhn.fhir.rest.api.SearchStyleEnum.class;
case "serverurl":
case "serverUrl": return java.lang.String.class;
case "sessioncookie":
Expand Down Expand Up @@ -203,6 +218,12 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "proxyPort": return target.getProxyPort();
case "proxyuser":
case "proxyUser": return target.getProxyUser();
case "resourcename":
case "resourceName": return target.getResourceName();
case "searchparameters":
case "searchParameters": return target.getSearchParameters();
case "searchstyle":
case "searchStyle": return target.getSearchStyle();
case "serverurl":
case "serverUrl": return target.getServerUrl();
case "sessioncookie":
Expand All @@ -223,6 +244,8 @@ public Object getCollectionValueType(Object target, String name, boolean ignoreC
switch (ignoreCase ? name.toLowerCase() : name) {
case "extraparameters":
case "extraParameters": return java.lang.Object.class;
case "searchparameters":
case "searchParameters": return java.util.List.class;
default: return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private FhirApiCollection() {
apiMethods.put(FhirReadApiMethod.class, FhirApiName.READ);

aliases.clear();
nullableArgs = Arrays.asList("extraParameters");
nullableArgs = Arrays.asList("searchParameters", "searchStyle", "extraParameters");
apiHelpers.put(FhirApiName.SEARCH, new ApiMethodHelper<>(FhirSearchApiMethod.class, aliases, nullableArgs));
apiMethods.put(FhirSearchApiMethod.class, FhirApiName.SEARCH);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@
*/
public enum FhirSearchApiMethod implements ApiMethod {

SEARCH_BY_RESOURCE(
org.hl7.fhir.instance.model.api.IBaseBundle.class,
"searchByResource",
arg("resourceName", String.class),
arg("searchParameters", java.util.Map.class),
arg("searchStyle", ca.uhn.fhir.rest.api.SearchStyleEnum.class),
arg("extraParameters", java.util.Map.class)),

SEARCH_BY_URL(
org.hl7.fhir.instance.model.api.IBaseBundle.class,
"searchByUrl",
Expand Down
Loading

0 comments on commit 75fb269

Please sign in to comment.