Add FHIRPath evaluation interceptor (#1769)
* Add FHIRPath evaluation interceptor * Add changelog
This commit is contained in:
parent
75402e38f6
commit
c2ae5a8326
|
@ -3,7 +3,7 @@ package ca.uhn.fhir.context;
|
|||
import ca.uhn.fhir.context.api.AddProfileTagEnum;
|
||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.i18n.HapiLocalizer;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
|
@ -625,12 +625,21 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a new FluentPath engine which can be used to exvaluate
|
||||
* @since 2.2
|
||||
* @deprecated Deprecated in HAPI FHIR 5.0.0. Use {@link #newFhirPath()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public IFhirPath newFluentPath() {
|
||||
return newFhirPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FhirPath engine which can be used to evaluate
|
||||
* path expressions over FHIR resources. Note that this engine will use the
|
||||
* {@link IValidationSupport context validation support} module which is
|
||||
* configured on the context at the time this method is called.
|
||||
* <p>
|
||||
* In other words, call {@link #setValidationSupport(IValidationSupport)} before
|
||||
* In other words, you may wish to call {@link #setValidationSupport(IValidationSupport)} before
|
||||
* calling {@link #newFluentPath()}
|
||||
* </p>
|
||||
* <p>
|
||||
|
@ -640,9 +649,9 @@ public class FhirContext {
|
|||
* {@link UnsupportedOperationException}
|
||||
* </p>
|
||||
*
|
||||
* @since 2.2
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public IFluentPath newFluentPath() {
|
||||
public IFhirPath newFhirPath() {
|
||||
return myVersion.createFluentPathExecutor(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package ca.uhn.fhir.fluentpath;
|
||||
package ca.uhn.fhir.fhirpath;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -23,18 +23,18 @@ package ca.uhn.fhir.fluentpath;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
/**
|
||||
* This exception is thrown if a FluentPath expression can not be executed successfully
|
||||
* This exception is thrown if a FHIRPath expression can not be executed successfully
|
||||
* for any reason
|
||||
*/
|
||||
public class FluentPathExecutionException extends InternalErrorException {
|
||||
public class FhirPathExecutionException extends InternalErrorException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public FluentPathExecutionException(Throwable theCause) {
|
||||
public FhirPathExecutionException(Throwable theCause) {
|
||||
super(theCause);
|
||||
}
|
||||
|
||||
public FluentPathExecutionException(String theMessage) {
|
||||
public FhirPathExecutionException(String theMessage) {
|
||||
super(theMessage);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ca.uhn.fhir.fluentpath;
|
||||
package ca.uhn.fhir.fhirpath;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -25,7 +25,7 @@ import java.util.Optional;
|
|||
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
|
||||
public interface IFluentPath {
|
||||
public interface IFhirPath {
|
||||
|
||||
/**
|
||||
* Apply the given FluentPath expression against the given input and return
|
|
@ -23,10 +23,10 @@ package ca.uhn.fhir.model.api;
|
|||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,7 @@ import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
|||
*/
|
||||
public interface IFhirVersion {
|
||||
|
||||
IFluentPath createFluentPathExecutor(FhirContext theFhirContext);
|
||||
IFhirPath createFluentPathExecutor(FhirContext theFhirContext);
|
||||
|
||||
IBaseResource generateProfile(RuntimeResourceDefinition theRuntimeResourceDefinition, String theServerBase);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
|||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
|
@ -120,7 +120,7 @@ public abstract class BaseNarrativeGenerator implements INarrativeGenerator {
|
|||
if (theFhirContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
|
||||
return Collections.singletonList(theResource);
|
||||
}
|
||||
IFluentPath fhirPath = theFhirContext.newFluentPath();
|
||||
IFhirPath fhirPath = theFhirContext.newFluentPath();
|
||||
return fhirPath.evaluate(theResource, theContextPath, IBase.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -259,6 +259,7 @@ public class Constants {
|
|||
* </p>
|
||||
*/
|
||||
public static final String EXT_META_SOURCE = "http://hapifhir.io/fhir/StructureDefinition/resource-meta-source";
|
||||
public static final String PARAM_FHIRPATH = "_fhirpath";
|
||||
|
||||
static {
|
||||
CHARSET_UTF8 = StandardCharsets.UTF_8;
|
||||
|
|
|
@ -238,7 +238,7 @@ public class ParametersUtil {
|
|||
addPart(theContext, theParameter, theName, coding);
|
||||
}
|
||||
|
||||
private static void addPart(FhirContext theContext, IBase theParameter, String theName, IBase theValue) {
|
||||
public static void addPart(FhirContext theContext, IBase theParameter, String theName, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(theParameter.getClass());
|
||||
BaseRuntimeChildDefinition partChild = def.getChildByName("part");
|
||||
|
||||
|
@ -252,4 +252,19 @@ public class ParametersUtil {
|
|||
|
||||
partChildElem.getChildByName("value[x]").getMutator().addValue(part, theValue);
|
||||
}
|
||||
|
||||
public static void addPartResource(FhirContext theContext, IBase theParameter, String theName, IBaseResource theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(theParameter.getClass());
|
||||
BaseRuntimeChildDefinition partChild = def.getChildByName("part");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> partChildElem = (BaseRuntimeElementCompositeDefinition<?>) partChild.getChildByName("part");
|
||||
IBase part = partChildElem.newInstance();
|
||||
partChild.getMutator().addValue(theParameter, part);
|
||||
|
||||
IPrimitiveType<String> name = (IPrimitiveType<String>) theContext.getElementDefinition("string").newInstance();
|
||||
name.setValue(theName);
|
||||
partChildElem.getChildByName("name").getMutator().addValue(part, name);
|
||||
|
||||
partChildElem.getChildByName("resource").getMutator().addValue(part, theValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.annotation.WebServlet;
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings({"serial", "RedundantThrows", "InnerClassMayBeStatic"})
|
||||
public class ServletExamples {
|
||||
|
||||
// START SNIPPET: loggingInterceptor
|
||||
|
@ -121,6 +121,24 @@ public class ServletExamples {
|
|||
}
|
||||
// END SNIPPET: exceptionInterceptor
|
||||
|
||||
// START SNIPPET: fhirPathInterceptor
|
||||
@WebServlet(urlPatterns = { "/fhir/*" }, displayName = "FHIR Server")
|
||||
public class RestfulServerWithFhirPath extends RestfulServer {
|
||||
|
||||
@Override
|
||||
protected void initialize() throws ServletException {
|
||||
|
||||
// ... define your resource providers here ...
|
||||
|
||||
// Now register the interceptor
|
||||
FhirPathFilterInterceptor interceptor = new FhirPathFilterInterceptor();
|
||||
registerInterceptor(interceptor);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// END SNIPPET: fhirPathInterceptor
|
||||
|
||||
// START SNIPPET: responseHighlighterInterceptor
|
||||
@WebServlet(urlPatterns = { "/fhir/*" }, displayName = "FHIR Server")
|
||||
public class RestfulServerWithResponseHighlighter extends RestfulServer {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: add
|
||||
issue: 1769
|
||||
title: A new built-in server interceptor called FhirPathFilterInterceptor has been added. This interceptor
|
||||
evaluates an arbitrary FHIRPath expression against the resource being returned and replaces the response
|
||||
with a Parameters resource containing the results of the evaluation.
|
|
@ -17,3 +17,11 @@
|
|||
[Migrating to HAPI FHIR 5.x](/hapi-fhir/docs/validation/instance_validator.html#migrating-to-hapi-fhir-5x)
|
||||
for details on how to account for this change in your code.
|
||||
"
|
||||
- item:
|
||||
issue: "1769"
|
||||
type: "change"
|
||||
title: "**Breaking Change**:
|
||||
The `IFluentPath` interface has been renamed to `IFhirPath`, and the `FhirContext#newFluentPath()` method
|
||||
has been replaced with an equivalent `FhirContext.newFhirPath()`. The FhirPath expression language was initially
|
||||
called FluentPath before being renamed, so this change brings HAPI FHIR inline with the correct naming.
|
||||
"
|
||||
|
|
|
@ -50,6 +50,52 @@ The following example shows how to register the ExceptionHandlingInterceptor.
|
|||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServletExamples.java|exceptionInterceptor}}
|
||||
```
|
||||
|
||||
# Response Customizing: Evaluate FHIRPath
|
||||
|
||||
The FhirPathFilterInterceptor looks for a request URL parameter in the form `_fhirpath=(expression)` in all REST requests. If this parameter is found, the value is treated as a [FHIRPath](http://hl7.org/fhirpath/) expression. The response resource will be replaced with a [Parameters](hl7.org/fhir/parameters.html) resource containing the results of the given expression applied against the response resource.
|
||||
|
||||
* [FhirPathFilterInterceptor JavaDoc](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/FhirPathFilterInterceptor.html)
|
||||
* [FhirPathFilterInterceptor Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/FhirPathFilterInterceptor.java)
|
||||
|
||||
The following example shows how to register the ExceptionHandlingInterceptor.
|
||||
|
||||
```java
|
||||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServletExamples.java|exceptionInterceptor}}
|
||||
```
|
||||
|
||||
An example URL to invoke this function is shown below:
|
||||
|
||||
```url
|
||||
https://hapi.fhir.org/baseR4/Patient?_fhirpath=Bundle.entry.resource.as(Patient).name&_pretty=true
|
||||
```
|
||||
|
||||
A sample response to this query is shown below:
|
||||
|
||||
```json
|
||||
{
|
||||
"resourceType": "Parameters",
|
||||
"parameter": [ {
|
||||
"name": "result",
|
||||
"part": [ {
|
||||
"name": "expression",
|
||||
"valueString": "Bundle.entry.resource.as(Patient).name"
|
||||
}, {
|
||||
"name": "result",
|
||||
"valueHumanName": {
|
||||
"family": "Simpson",
|
||||
"given": [ "Homer", "Jay" ]
|
||||
}
|
||||
}, {
|
||||
"name": "result",
|
||||
"valueHumanName": {
|
||||
"family": "Simpson",
|
||||
"given": [ "Grandpa" ]
|
||||
}
|
||||
} ]
|
||||
} ]
|
||||
}
|
||||
```
|
||||
|
||||
# Validation: Request and Response Validation
|
||||
|
||||
HAPI FHIR provides a pair of interceptors that can be used to validate incoming requests received by the server, as well as outgoing responses generated by the server.
|
||||
|
|
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
|||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.interceptor.BanUnsupportedHttpMethodsInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.FhirPathFilterInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import ca.uhn.fhirtest.config.TestDstu2Config;
|
||||
import ca.uhn.fhirtest.config.TestDstu3Config;
|
||||
|
@ -198,6 +199,11 @@ public class TestRestfulServer extends RestfulServer {
|
|||
CorsInterceptor corsInterceptor = new CorsInterceptor();
|
||||
registerInterceptor(corsInterceptor);
|
||||
|
||||
/*
|
||||
* Enable FHIRPath evaluation
|
||||
*/
|
||||
registerInterceptor(new FhirPathFilterInterceptor());
|
||||
|
||||
/*
|
||||
* Enable version conversion
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.fhirpath.FhirPathExecutionException;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.interceptor.api.Hook;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.ResponseDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/**
|
||||
* This interceptor looks for a URL parameter on requests called <code>_fhirpath</code> and
|
||||
* replaces the resource being returned with a Parameters resource containing the results of
|
||||
* the given FHIRPath expression evaluated against the resource that would otherwise
|
||||
* have been returned.
|
||||
*
|
||||
* @see <a href="https://hapifhir.io/hapi-fhir/docs/interceptors/built_in_server_interceptors.html#response-customizing-evaluate-fhirpath">Interceptors - Response Customization: Evaluate FHIRPath</a>
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public class FhirPathFilterInterceptor {
|
||||
|
||||
@Hook(Pointcut.SERVER_OUTGOING_RESPONSE)
|
||||
public void preProcessOutgoingResponse(RequestDetails theRequestDetails, ResponseDetails theResponseDetails) {
|
||||
IBaseResource responseResource = theResponseDetails.getResponseResource();
|
||||
if (responseResource != null) {
|
||||
String[] fhirPathParams = theRequestDetails.getParameters().get(Constants.PARAM_FHIRPATH);
|
||||
if (fhirPathParams != null) {
|
||||
|
||||
FhirContext ctx = theRequestDetails.getFhirContext();
|
||||
IBaseParameters responseParameters = ParametersUtil.newInstance(ctx);
|
||||
|
||||
for (String expression : fhirPathParams) {
|
||||
if (isNotBlank(expression)) {
|
||||
IBase resultPart = ParametersUtil.addParameterToParameters(ctx, responseParameters, "result");
|
||||
ParametersUtil.addPartString(ctx, resultPart, "expression", expression);
|
||||
|
||||
IFhirPath fhirPath = ctx.newFhirPath();
|
||||
List<IBase> outputs;
|
||||
try {
|
||||
outputs = fhirPath.evaluate(responseResource, expression, IBase.class);
|
||||
} catch (FhirPathExecutionException e) {
|
||||
throw new InvalidRequestException("Error parsing FHIRPath expression: " + e.getMessage());
|
||||
}
|
||||
|
||||
for (IBase nextOutput : outputs) {
|
||||
if (nextOutput instanceof IBaseResource) {
|
||||
ParametersUtil.addPartResource(ctx, resultPart, "result", (IBaseResource) nextOutput);
|
||||
} else {
|
||||
ParametersUtil.addPart(ctx, resultPart, "result", nextOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theResponseDetails.setResponseResource(responseParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -60,7 +60,7 @@ import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
|
|||
import ca.uhn.fhir.context.RuntimeResourceBlockDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.IFluentPath;
|
||||
import ca.uhn.fhir.model.api.ICompositeDatatype;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.hl7.fhir.dstu2016may.model.*;
|
|||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
||||
|
@ -41,7 +41,7 @@ public class FhirDstu2_1 implements IFhirVersion {
|
|||
private String myId;
|
||||
|
||||
@Override
|
||||
public IFluentPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
public IFhirPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
throw new UnsupportedOperationException("FluentPath is not supported in DSTU2 contexts");
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,11 @@ package ca.uhn.fhir.model.dstu2;
|
|||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.base.composite.*;
|
||||
import ca.uhn.fhir.model.dstu2.composite.*;
|
||||
|
@ -42,7 +42,7 @@ public class FhirDstu2 implements IFhirVersion {
|
|||
private String myId;
|
||||
|
||||
@Override
|
||||
public IFluentPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
public IFhirPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
throw new UnsupportedOperationException("FluentPath is not supported in DSTU2 contexts");
|
||||
}
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.dstu3.hapi.fluentpath.FluentPathDstu3;
|
||||
import org.hl7.fhir.dstu3.hapi.fluentpath.FhirPathDstu3;
|
||||
import org.hl7.fhir.dstu3.hapi.rest.server.Dstu3BundleFactory;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
@ -44,8 +44,8 @@ public class FhirDstu3 implements IFhirVersion {
|
|||
private String myId;
|
||||
|
||||
@Override
|
||||
public IFluentPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
return new FluentPathDstu3(theFhirContext);
|
||||
public IFhirPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
return new FhirPathDstu3(theFhirContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,8 +2,8 @@ package org.hl7.fhir.dstu3.hapi.fluentpath;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.fluentpath.FluentPathExecutionException;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.FhirPathExecutionException;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
|
||||
import org.hl7.fhir.dstu3.model.Base;
|
||||
import org.hl7.fhir.dstu3.utils.FHIRPathEngine;
|
||||
|
@ -13,11 +13,11 @@ import org.hl7.fhir.instance.model.api.IBase;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FluentPathDstu3 implements IFluentPath {
|
||||
public class FhirPathDstu3 implements IFhirPath {
|
||||
|
||||
private FHIRPathEngine myEngine;
|
||||
|
||||
public FluentPathDstu3(FhirContext theCtx) {
|
||||
public FhirPathDstu3(FhirContext theCtx) {
|
||||
IValidationSupport validationSupport = theCtx.getValidationSupport();
|
||||
myEngine = new FHIRPathEngine(new HapiWorkerContext(theCtx, validationSupport));
|
||||
}
|
||||
|
@ -29,12 +29,12 @@ public class FluentPathDstu3 implements IFluentPath {
|
|||
try {
|
||||
result = myEngine.evaluate((Base)theInput, thePath);
|
||||
} catch (FHIRException e) {
|
||||
throw new FluentPathExecutionException(e);
|
||||
throw new FhirPathExecutionException(e);
|
||||
}
|
||||
|
||||
for (Base next : result) {
|
||||
if (!theReturnType.isAssignableFrom(next.getClass())) {
|
||||
throw new FluentPathExecutionException("FluentPath expression \"" + thePath + "\" returned unexpected type " + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName());
|
||||
throw new FhirPathExecutionException("FluentPath expression \"" + thePath + "\" returned unexpected type " + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName());
|
||||
}
|
||||
}
|
||||
|
|
@ -24,12 +24,12 @@ import java.io.InputStream;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.dstu2.model.*;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
||||
|
@ -41,7 +41,7 @@ public class FhirDstu2Hl7Org implements IFhirVersion {
|
|||
private String myId;
|
||||
|
||||
@Override
|
||||
public IFluentPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
public IFhirPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
throw new UnsupportedOperationException("FluentPath is not supported in DSTU2 contexts");
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,12 @@ import java.util.List;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.hl7.fhir.r4.hapi.fluentpath.FluentPathR4;
|
||||
import org.hl7.fhir.r4.hapi.fluentpath.FhirPathR4;
|
||||
import org.hl7.fhir.r4.hapi.rest.server.R4BundleFactory;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
||||
|
@ -42,8 +42,8 @@ public class FhirR4 implements IFhirVersion {
|
|||
private String myId;
|
||||
|
||||
@Override
|
||||
public IFluentPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
return new FluentPathR4(theFhirContext);
|
||||
public IFhirPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
return new FhirPathR4(theFhirContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,8 +2,8 @@ package org.hl7.fhir.r4.hapi.fluentpath;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.fluentpath.FluentPathExecutionException;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.FhirPathExecutionException;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
|
||||
|
@ -13,11 +13,11 @@ import org.hl7.fhir.r4.utils.FHIRPathEngine;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FluentPathR4 implements IFluentPath {
|
||||
public class FhirPathR4 implements IFhirPath {
|
||||
|
||||
private FHIRPathEngine myEngine;
|
||||
|
||||
public FluentPathR4(FhirContext theCtx) {
|
||||
public FhirPathR4(FhirContext theCtx) {
|
||||
IValidationSupport validationSupport = theCtx.getValidationSupport();
|
||||
myEngine = new FHIRPathEngine(new HapiWorkerContext(theCtx, validationSupport));
|
||||
}
|
||||
|
@ -29,12 +29,12 @@ public class FluentPathR4 implements IFluentPath {
|
|||
try {
|
||||
result = myEngine.evaluate((Base) theInput, thePath);
|
||||
} catch (FHIRException e) {
|
||||
throw new FluentPathExecutionException(e);
|
||||
throw new FhirPathExecutionException(e);
|
||||
}
|
||||
|
||||
for (Base next : result) {
|
||||
if (!theReturnType.isAssignableFrom(next.getClass())) {
|
||||
throw new FluentPathExecutionException("FluentPath expression \"" + thePath + "\" returned unexpected type " + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName());
|
||||
throw new FhirPathExecutionException("FluentPath expression \"" + thePath + "\" returned unexpected type " + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.test.utilities.HttpClientRule;
|
||||
import ca.uhn.fhir.test.utilities.server.HashMapResourceProviderRule;
|
||||
import ca.uhn.fhir.test.utilities.server.RestfulServerRule;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class FhirPathFilterInterceptorTest {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(FhirPathFilterInterceptorTest.class);
|
||||
@ClassRule
|
||||
public static HttpClientRule ourClientRule = new HttpClientRule();
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
@ClassRule
|
||||
public static RestfulServerRule ourServerRule = new RestfulServerRule(ourCtx);
|
||||
@ClassRule
|
||||
public static HashMapResourceProviderRule<Patient> ourProviderRule = new HashMapResourceProviderRule<>(ourServerRule, Patient.class);
|
||||
private IGenericClient myClient;
|
||||
private String myBaseUrl;
|
||||
private CloseableHttpClient myHttpClient;
|
||||
private IIdType myPatientId;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ourProviderRule.clear();
|
||||
ourServerRule.getRestfulServer().getInterceptorService().unregisterAllInterceptors();
|
||||
ourServerRule.getRestfulServer().getInterceptorService().registerInterceptor(new FhirPathFilterInterceptor());
|
||||
|
||||
myClient = ourServerRule.getFhirClient();
|
||||
myBaseUrl = "http://localhost:" + ourServerRule.getPort();
|
||||
myHttpClient = ourClientRule.getClient();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnfilteredResponse() throws IOException {
|
||||
createPatient();
|
||||
|
||||
HttpGet request = new HttpGet(myPatientId.getValue());
|
||||
try (CloseableHttpResponse response = myHttpClient.execute(request)) {
|
||||
String responseText = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response:\n{}", responseText);
|
||||
assertThat(responseText, containsString("\"system\": \"http://identifiers/1\""));
|
||||
assertThat(responseText, containsString("\"given\": [ \"Homer\", \"Jay\" ]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUnfilteredResponse_WithResponseHighlightingInterceptor() throws IOException {
|
||||
ourServerRule.getRestfulServer().registerInterceptor(new ResponseHighlighterInterceptor());
|
||||
createPatient();
|
||||
|
||||
HttpGet request = new HttpGet(myPatientId.getValue() + "?_format=" + Constants.FORMATS_HTML_JSON);
|
||||
try (CloseableHttpResponse response = myHttpClient.execute(request)) {
|
||||
String responseText = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response:\n{}", responseText);
|
||||
assertThat(responseText, containsString("<span class='hlTagName'>"system"</span>: <span class='hlQuot'>"http://identifiers/1""));
|
||||
assertThat(responseText, containsString("<span class='hlTagName'>"given"</span>: <span class='hlControl'>[</span> <span class='hlTagName'>"Homer"</span><span class='hlControl'>,</span> <span class='hlTagName'>"Jay"</span> ]</div>"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilteredResponse() throws IOException {
|
||||
createPatient();
|
||||
|
||||
HttpGet request = new HttpGet(myPatientId + "?_fhirpath=Patient.identifier&_pretty=true");
|
||||
try (CloseableHttpResponse response = myHttpClient.execute(request)) {
|
||||
String responseText = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response:\n{}", responseText);
|
||||
assertThat(responseText, containsString("\"system\": \"http://identifiers/1\""));
|
||||
assertThat(responseText, not(containsString("\"given\": [ \"Homer\", \"Jay\" ]")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilteredResponse_ExpressionReturnsResource() throws IOException {
|
||||
createPatient();
|
||||
|
||||
HttpGet request = new HttpGet(myPatientId + "?_fhirpath=Patient&_pretty=true");
|
||||
try (CloseableHttpResponse response = myHttpClient.execute(request)) {
|
||||
String responseText = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response:\n{}", responseText);
|
||||
assertThat(responseText, containsString("\"resource\": {"));
|
||||
assertThat(responseText, containsString("\"system\": \"http://identifiers/1\""));
|
||||
assertThat(responseText, containsString("\"given\": [ \"Homer\", \"Jay\" ]"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilteredResponse_ExpressionIsInvalid() throws IOException {
|
||||
createPatient();
|
||||
|
||||
HttpGet request = new HttpGet(myPatientId + "?_fhirpath=" + UrlUtil.escapeUrlParam("***"));
|
||||
try (CloseableHttpResponse response = myHttpClient.execute(request)) {
|
||||
String responseText = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response:\n{}", responseText);
|
||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||
assertThat(responseText, containsString("Error parsing FHIRPath expression: Error performing *: left operand has more than one value"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilteredResponseBundle() throws IOException {
|
||||
createPatient();
|
||||
|
||||
HttpGet request = new HttpGet(myBaseUrl + "/Patient?_fhirpath=Bundle.entry.resource.as(Patient).name&_pretty=true");
|
||||
try (CloseableHttpResponse response = myHttpClient.execute(request)) {
|
||||
String responseText = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response:\n{}", responseText);
|
||||
assertThat(responseText, containsString(
|
||||
" \"valueHumanName\": {\n" +
|
||||
" \"family\": \"Simpson\",\n" +
|
||||
" \"given\": [ \"Homer\", \"Jay\" ]\n" +
|
||||
" }"
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilteredResponse_WithResponseHighlightingInterceptor() throws IOException {
|
||||
ourServerRule.getRestfulServer().registerInterceptor(new ResponseHighlighterInterceptor());
|
||||
createPatient();
|
||||
|
||||
HttpGet request = new HttpGet(myPatientId + "?_fhirpath=Patient.identifier&_format=" + Constants.FORMATS_HTML_JSON);
|
||||
try (CloseableHttpResponse response = myHttpClient.execute(request)) {
|
||||
String responseText = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response:\n{}", responseText);
|
||||
assertThat(responseText, containsString("<span class='hlTagName'>"system"</span>: <span class='hlQuot'>"http://identifiers/1""));
|
||||
assertThat(responseText, not(containsString("<span class='hlTagName'>"given"</span>: <span class='hlControl'>[</span> <span class='hlTagName'>"Homer"</span><span class='hlControl'>,</span> <span class='hlTagName'>"Jay"</span> ]</div>")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void createPatient() {
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
p.addIdentifier().setSystem("http://identifiers/1").setValue("value-1");
|
||||
p.addIdentifier().setSystem("http://identifiers/2").setValue("value-2");
|
||||
p.addName().setFamily("Simpson").addGiven("Homer").addGiven("Jay");
|
||||
p.addName().setFamily("Simpson").addGiven("Grandpa");
|
||||
myPatientId = myClient.create().resource(p).execute().getId().withServerBase(myBaseUrl, "Patient");
|
||||
}
|
||||
|
||||
}
|
|
@ -24,7 +24,7 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
||||
|
@ -52,7 +52,7 @@ public class FhirR5 implements IFhirVersion {
|
|||
private String myId;
|
||||
|
||||
@Override
|
||||
public IFluentPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
public IFhirPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
return new FhirPathR5(theFhirContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ package org.hl7.fhir.r5.hapi.fhirpath;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.fluentpath.FluentPathExecutionException;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.fhirpath.FhirPathExecutionException;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.r5.hapi.ctx.HapiWorkerContext;
|
||||
|
@ -13,7 +13,7 @@ import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FhirPathR5 implements IFluentPath {
|
||||
public class FhirPathR5 implements IFhirPath {
|
||||
|
||||
private FHIRPathEngine myEngine;
|
||||
|
||||
|
@ -29,12 +29,12 @@ public class FhirPathR5 implements IFluentPath {
|
|||
try {
|
||||
result = myEngine.evaluate((Base) theInput, thePath);
|
||||
} catch (FHIRException e) {
|
||||
throw new FluentPathExecutionException(e);
|
||||
throw new FhirPathExecutionException(e);
|
||||
}
|
||||
|
||||
for (Base next : result) {
|
||||
if (!theReturnType.isAssignableFrom(next.getClass())) {
|
||||
throw new FluentPathExecutionException("FluentPath expression \"" + thePath + "\" returned unexpected type " + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName());
|
||||
throw new FhirPathExecutionException("FluentPath expression \"" + thePath + "\" returned unexpected type " + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package ca.uhn.fhir.test.utilities;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR Test Utilities
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2020 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
public class HttpClientRule implements TestRule {
|
||||
private CloseableHttpClient myClient;
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement theBase, Description theDescription) {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
startClient();
|
||||
theBase.evaluate();
|
||||
stopClient();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private void stopClient() throws Exception {
|
||||
myClient.close();
|
||||
}
|
||||
|
||||
private void startClient() {
|
||||
myClient = HttpClientBuilder
|
||||
.create()
|
||||
.build();
|
||||
}
|
||||
|
||||
public CloseableHttpClient getClient() {
|
||||
return myClient;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package ca.uhn.fhir.fluentpath;
|
||||
package ca.uhn.fhir.fhirpath;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
@ -21,7 +21,7 @@ public class FluentPathTest {
|
|||
p.addName().setFamily("N1F1").addGiven("N1G1").addGiven("N1G2");
|
||||
p.addName().setFamily("N2F1").addGiven("N2G1").addGiven("N2G2");
|
||||
|
||||
IFluentPath fp = ourCtx.newFluentPath();
|
||||
IFhirPath fp = ourCtx.newFluentPath();
|
||||
List<HumanName> names = fp.evaluate(p, "Patient.name", HumanName.class);
|
||||
assertEquals(2, names.size());
|
||||
assertEquals("N1F1", names.get(0).getFamily());
|
||||
|
@ -36,7 +36,7 @@ public class FluentPathTest {
|
|||
p.addName().setFamily("N1F1").addGiven("N1G1").addGiven("N1G2");
|
||||
p.addName().setFamily("N2F1").addGiven("N2G1").addGiven("N2G2");
|
||||
|
||||
IFluentPath fp = ourCtx.newFluentPath();
|
||||
IFhirPath fp = ourCtx.newFluentPath();
|
||||
List<HumanName> names = fp.evaluate(p, "Patient.nameFOO", HumanName.class);
|
||||
assertEquals(0, names.size());
|
||||
}
|
||||
|
@ -47,10 +47,10 @@ public class FluentPathTest {
|
|||
p.addName().setFamily("N1F1").addGiven("N1G1").addGiven("N1G2");
|
||||
p.addName().setFamily("N2F1").addGiven("N2G1").addGiven("N2G2");
|
||||
|
||||
IFluentPath fp = ourCtx.newFluentPath();
|
||||
IFhirPath fp = ourCtx.newFluentPath();
|
||||
try {
|
||||
fp.evaluate(p, "Patient....nameFOO", HumanName.class);
|
||||
} catch (FluentPathExecutionException e) {
|
||||
} catch (FhirPathExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("termination at unexpected token"));
|
||||
}
|
||||
}
|
||||
|
@ -61,10 +61,10 @@ public class FluentPathTest {
|
|||
p.addName().setFamily("N1F1").addGiven("N1G1").addGiven("N1G2");
|
||||
p.addName().setFamily("N2F1").addGiven("N2G1").addGiven("N2G2");
|
||||
|
||||
IFluentPath fp = ourCtx.newFluentPath();
|
||||
IFhirPath fp = ourCtx.newFluentPath();
|
||||
try {
|
||||
fp.evaluate(p, "Patient.name", StringType.class);
|
||||
} catch (FluentPathExecutionException e) {
|
||||
} catch (FhirPathExecutionException e) {
|
||||
assertEquals("FluentPath expression \"Patient.name\" returned unexpected type HumanName - Expected org.hl7.fhir.dstu3.model.StringType", e.getMessage());
|
||||
}
|
||||
}
|
|
@ -23,11 +23,11 @@ package ca.uhn.fhir.model.dstu2;
|
|||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.base.composite.*;
|
||||
import ca.uhn.fhir.model.dstu2.composite.*;
|
||||
|
@ -41,7 +41,7 @@ public class FhirDstu2 implements IFhirVersion {
|
|||
private String myId;
|
||||
|
||||
@Override
|
||||
public IFluentPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
public IFhirPath createFluentPathExecutor(FhirContext theFhirContext) {
|
||||
throw new UnsupportedOperationException("FluentPath is not supported in DSTU2 contexts");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue