
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.IHostApplicationServices; 014import org.hl7.fhir.dstu3.fhirpath.TypeDetails; 015import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext; 016import org.hl7.fhir.dstu3.model.Base; 017import org.hl7.fhir.dstu3.model.IdType; 018import org.hl7.fhir.dstu3.model.ValueSet; 019import org.hl7.fhir.exceptions.FHIRException; 020import org.hl7.fhir.exceptions.PathEngineException; 021import org.hl7.fhir.instance.model.api.IBase; 022import org.hl7.fhir.utilities.fhirpath.FHIRPathConstantEvaluationMode; 023 024import java.util.List; 025import java.util.Optional; 026 027public class FhirPathDstu3 implements IFhirPath { 028 029 private final FHIRPathEngine myEngine; 030 031 public FhirPathDstu3(FhirContext theCtx) { 032 IValidationSupport validationSupport = theCtx.getValidationSupport(); 033 myEngine = new FHIRPathEngine(new HapiWorkerContext(theCtx, validationSupport)); 034 } 035 036 @SuppressWarnings("unchecked") 037 @Override 038 public <T extends IBase> List<T> evaluate(IBase theInput, String thePath, Class<T> theReturnType) { 039 ExpressionNode parsed; 040 try { 041 parsed = myEngine.parse(thePath); 042 } catch (FHIRException e) { 043 throw new FhirPathExecutionException(Msg.code(2408) + e); 044 } 045 return (List<T>) evaluate(theInput, parsed, theReturnType); 046 } 047 048 @SuppressWarnings("unchecked") 049 @Override 050 public <T extends IBase> List<T> evaluate( 051 IBase theInput, IParsedExpression theParsedExpression, Class<T> theReturnType) { 052 ExpressionNode expressionNode = ((ParsedExpression) theParsedExpression).myParsedExpression; 053 return (List<T>) evaluate(theInput, expressionNode, theReturnType); 054 } 055 056 @Nonnull 057 private <T extends IBase> List<Base> evaluate( 058 IBase theInput, ExpressionNode expressionNode, Class<T> theReturnType) { 059 List<Base> result; 060 try { 061 result = myEngine.evaluate((Base) theInput, expressionNode); 062 } catch (FHIRException e) { 063 throw new FhirPathExecutionException(Msg.code(607) + e); 064 } 065 066 for (IBase next : result) { 067 if (!theReturnType.isAssignableFrom(next.getClass())) { 068 throw new FhirPathExecutionException(Msg.code(608) + "FhirPath expression returned unexpected type " 069 + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName()); 070 } 071 } 072 return result; 073 } 074 075 @Override 076 public <T extends IBase> Optional<T> evaluateFirst(IBase theInput, String thePath, Class<T> theReturnType) { 077 return evaluate(theInput, thePath, theReturnType).stream().findFirst(); 078 } 079 080 @Override 081 public <T extends IBase> Optional<T> evaluateFirst( 082 IBase theInput, IParsedExpression theParsedExpression, Class<T> theReturnType) { 083 return evaluate(theInput, theParsedExpression, theReturnType).stream().findFirst(); 084 } 085 086 @Override 087 public IParsedExpression parse(String theExpression) { 088 return new ParsedExpression(myEngine.parse(theExpression)); 089 } 090 091 @Override 092 public void setEvaluationContext(@Nonnull IFhirPathEvaluationContext theEvaluationContext) { 093 myEngine.setHostServices(new IHostApplicationServices() { 094 095 @Override 096 public List<Base> resolveConstant( 097 FHIRPathEngine engine, Object appContext, String name, FHIRPathConstantEvaluationMode mode) 098 throws PathEngineException { 099 return null; 100 } 101 102 @Override 103 public TypeDetails resolveConstantType( 104 FHIRPathEngine engine, Object appContext, String name, FHIRPathConstantEvaluationMode mode) 105 throws PathEngineException { 106 return null; 107 } 108 109 @Override 110 public boolean log(String argument, List<Base> focus) { 111 return false; 112 } 113 114 @Override 115 public FunctionDetails resolveFunction(FHIRPathEngine engine, String functionName) { 116 return null; 117 } 118 119 @Override 120 public TypeDetails checkFunction( 121 FHIRPathEngine engine, 122 Object appContext, 123 String functionName, 124 TypeDetails focus, 125 List<TypeDetails> parameters) 126 throws PathEngineException { 127 return null; 128 } 129 130 @Override 131 public List<Base> executeFunction( 132 FHIRPathEngine engine, 133 Object appContext, 134 List<Base> focus, 135 String functionName, 136 List<List<Base>> parameters) { 137 return null; 138 } 139 140 @Override 141 public Base resolveReference(FHIRPathEngine engine, Object appContext, String theUrl, Base refContext) 142 throws FHIRException { 143 return (Base) theEvaluationContext.resolveReference(new IdType(theUrl), null); 144 } 145 146 @Override 147 public boolean conformsToProfile(FHIRPathEngine engine, Object appContext, Base item, String url) 148 throws FHIRException { 149 return false; 150 } 151 152 @Override 153 public ValueSet resolveValueSet(FHIRPathEngine engine, Object appContext, String url) { 154 return null; 155 } 156 157 @Override 158 public boolean paramIsType(String name, int index) { 159 return false; 160 } 161 }); 162 } 163 164 private static class ParsedExpression implements IParsedExpression { 165 166 private final ExpressionNode myParsedExpression; 167 168 public ParsedExpression(ExpressionNode theParsedExpression) { 169 myParsedExpression = theParsedExpression; 170 } 171 } 172}