001package org.hl7.fhir.r4.hapi.fluentpath;
002
003import ca.uhn.fhir.context.FhirContext;
004import ca.uhn.fhir.fluentpath.FluentPathExecutionException;
005import ca.uhn.fhir.fluentpath.IFluentPath;
006import org.hl7.fhir.exceptions.FHIRException;
007import org.hl7.fhir.instance.model.api.IBase;
008import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
009import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
010import org.hl7.fhir.r4.model.Base;
011import org.hl7.fhir.r4.utils.FHIRPathEngine;
012
013import java.util.List;
014import java.util.Optional;
015
016public class FluentPathR4 implements IFluentPath {
017
018  private FHIRPathEngine myEngine;
019
020  public FluentPathR4(FhirContext theCtx) {
021    if (!(theCtx.getValidationSupport() instanceof IValidationSupport)) {
022      throw new IllegalStateException("Validation support module configured on context appears to be for the wrong FHIR version- Does not extend " + IValidationSupport.class.getName());
023    }
024    IValidationSupport validationSupport = (IValidationSupport) theCtx.getValidationSupport();
025    myEngine = new FHIRPathEngine(new HapiWorkerContext(theCtx, validationSupport));
026  }
027
028  @SuppressWarnings("unchecked")
029  @Override
030  public <T extends IBase> List<T> evaluate(IBase theInput, String thePath, Class<T> theReturnType) {
031    List<Base> result;
032    try {
033      result = myEngine.evaluate((Base) theInput, thePath);
034    } catch (FHIRException e) {
035      throw new FluentPathExecutionException(e);
036    }
037
038    for (Base next : result) {
039      if (!theReturnType.isAssignableFrom(next.getClass())) {
040        throw new FluentPathExecutionException("FluentPath expression \"" + thePath + "\" returned unexpected type " + next.getClass().getSimpleName() + " - Expected " + theReturnType.getName());
041      }
042    }
043
044    return (List<T>) result;
045  }
046
047  @Override
048  public <T extends IBase> Optional<T> evaluateFirst(IBase theInput, String thePath, Class<T> theReturnType) {
049    return evaluate(theInput, thePath, theReturnType).stream().findFirst();
050  }
051
052
053}