001package org.hl7.fhir.dstu3.hapi.fluentpath; 002 003import ca.uhn.fhir.context.FhirContext; 004import ca.uhn.fhir.context.support.IValidationSupport; 005import ca.uhn.fhir.fhirpath.FhirPathExecutionException; 006import ca.uhn.fhir.fhirpath.IFhirPath; 007import ca.uhn.fhir.fhirpath.IFhirPathEvaluationContext; 008import ca.uhn.fhir.i18n.Msg; 009import jakarta.annotation.Nonnull; 010import org.hl7.fhir.dstu3.fhirpath.ExpressionNode; 011import org.hl7.fhir.dstu3.fhirpath.FHIRPathEngine; 012import org.hl7.fhir.dstu3.fhirpath.FHIRPathUtilityClasses.FunctionDetails; 013import org.hl7.fhir.dstu3.fhirpath.TypeDetails; 014import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext; 015import org.hl7.fhir.dstu3.model.Base; 016import org.hl7.fhir.dstu3.model.IdType; 017import org.hl7.fhir.exceptions.FHIRException; 018import org.hl7.fhir.exceptions.PathEngineException; 019import org.hl7.fhir.instance.model.api.IBase; 020 021import java.util.List; 022import java.util.Optional; 023 024public class FhirPathDstu3 implements IFhirPath { 025 026 private final FHIRPathEngine myEngine; 027 028 public FhirPathDstu3(FhirContext theCtx) { 029 IValidationSupport validationSupport = theCtx.getValidationSupport(); 030 myEngine = new FHIRPathEngine(new HapiWorkerContext(theCtx, validationSupport)); 031 } 032 033 @SuppressWarnings("unchecked") 034 @Override 035 public <T extends IBase> List<T> evaluate(IBase theInput, String thePath, Class<T> theReturnType) { 036 ExpressionNode parsed; 037 try { 038 parsed = myEngine.parse(thePath); 039 } catch (FHIRException e) { 040 throw new FhirPathExecutionException(Msg.code(2408) + e); 041 } 042 return (List<T>) evaluate(theInput, parsed, theReturnType); 043 } 044 045 @SuppressWarnings("unchecked") 046 @Override 047 public <T extends IBase> List<T> evaluate( 048 IBase theInput, IParsedExpression theParsedExpression, Class<T> theReturnType) { 049 ExpressionNode expressionNode = ((ParsedExpression) theParsedExpression).myParsedExpression; 050 return (List<T>) evaluate(theInput, expressionNode, theReturnType); 051 } 052 053 @Nonnull 054 private <T extends IBase> List<Base> evaluate( 055 IBase theInput, ExpressionNode expressionNode, Class<T> theReturnType) { 056 List<Base> result; 057 try { 058 result = myEngine.evaluate((Base) theInput, expressionNode); 059 } catch (FHIRException e) { 060 throw new FhirPathExecutionException(Msg.code(607) + e); 061 } 062 063 for (IBase next : result) { 064 if (!theReturnType.isAssignableFrom(next.getClass())) { 065 throw new FhirPathExecutionException(Msg.code(608) + "FhirPath expression returned unexpected type " 066 + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName()); 067 } 068 } 069 return result; 070 } 071 072 @Override 073 public <T extends IBase> Optional<T> evaluateFirst(IBase theInput, String thePath, Class<T> theReturnType) { 074 return evaluate(theInput, thePath, theReturnType).stream().findFirst(); 075 } 076 077 @Override 078 public <T extends IBase> Optional<T> evaluateFirst( 079 IBase theInput, IParsedExpression theParsedExpression, Class<T> theReturnType) { 080 return evaluate(theInput, theParsedExpression, theReturnType).stream().findFirst(); 081 } 082 083 @Override 084 public IParsedExpression parse(String theExpression) { 085 return new ParsedExpression(myEngine.parse(theExpression)); 086 } 087 088 @Override 089 public void setEvaluationContext(@Nonnull IFhirPathEvaluationContext theEvaluationContext) { 090 myEngine.setHostServices(new FHIRPathEngine.IEvaluationContext() { 091 092 @Override 093 public Base resolveConstant(Object appContext, String name) throws PathEngineException { 094 return null; 095 } 096 097 @Override 098 public TypeDetails resolveConstantType(Object appContext, String name) throws PathEngineException { 099 return null; 100 } 101 102 @Override 103 public boolean log(String argument, List<Base> focus) { 104 return false; 105 } 106 107 @Override 108 public FunctionDetails resolveFunction(String functionName) { 109 return null; 110 } 111 112 @Override 113 public TypeDetails checkFunction(Object appContext, String functionName, List<TypeDetails> parameters) 114 throws PathEngineException { 115 return null; 116 } 117 118 @Override 119 public List<Base> executeFunction(Object appContext, String functionName, List<List<Base>> parameters) { 120 return null; 121 } 122 123 @Override 124 public Base resolveReference(Object appContext, String theUrl) throws FHIRException { 125 return (Base) theEvaluationContext.resolveReference(new IdType(theUrl), null); 126 } 127 }); 128 } 129 130 private static class ParsedExpression implements IParsedExpression { 131 132 private final ExpressionNode myParsedExpression; 133 134 public ParsedExpression(ExpressionNode theParsedExpression) { 135 myParsedExpression = theParsedExpression; 136 } 137 } 138}