Search in sources :

Example 6 with BooleanPath

use of au.csiro.pathling.fhirpath.element.BooleanPath in project pathling by aehrc.

the class MemberOfFunctionTest method memberOfCodeableConcept.

@Test
void memberOfCodeableConcept() {
    final Coding coding1 = new Coding(LOINC_URL, "10337-4", "Procollagen type I [Mass/volume] in Serum");
    final Coding coding2 = new Coding(LOINC_URL, "10428-1", "Varicella zoster virus immune globulin given [Volume]");
    final Coding coding3 = new Coding(LOINC_URL, "10555-1", null);
    final Coding coding4 = new Coding(LOINC_URL, "10665-8", "Fungus colony count [#/volume] in Unspecified specimen by Environmental culture");
    final Coding coding5 = new Coding(SNOMED_URL, "416399002", "Procollagen type I amino-terminal propeptide level");
    final CodeableConcept codeableConcept1 = new CodeableConcept(coding1);
    codeableConcept1.addCoding(coding5);
    final CodeableConcept codeableConcept2 = new CodeableConcept(coding2);
    final CodeableConcept codeableConcept3 = new CodeableConcept(coding3);
    final CodeableConcept codeableConcept4 = new CodeableConcept(coding3);
    final CodeableConcept codeableConcept5 = new CodeableConcept(coding4);
    final CodeableConcept codeableConcept6 = new CodeableConcept(coding1);
    final Optional<ElementDefinition> optionalDefinition = FhirHelpers.getChildOfResource(fhirContext, "DiagnosticReport", "code");
    assertTrue(optionalDefinition.isPresent());
    final ElementDefinition definition = optionalDefinition.get();
    final Dataset<Row> inputDataset = new DatasetBuilder(spark).withIdColumn().withStructTypeColumns(codeableConceptStructType()).withRow("diagnosticreport-1", rowFromCodeableConcept(codeableConcept1)).withRow("diagnosticreport-2", rowFromCodeableConcept(codeableConcept2)).withRow("diagnosticreport-3", rowFromCodeableConcept(codeableConcept3)).withRow("diagnosticreport-4", rowFromCodeableConcept(codeableConcept4)).withRow("diagnosticreport-5", rowFromCodeableConcept(codeableConcept5)).withRow("diagnosticreport-6", rowFromCodeableConcept(codeableConcept6)).withRow("diagnosticreport-7", null).buildWithStructValue();
    final ElementPath inputExpression = new ElementPathBuilder(spark).dataset(inputDataset).idAndValueColumns().expression("DiagnosticReport.code").singular(true).definition(definition).buildDefined();
    final StringLiteralPath argumentExpression = StringLiteralPath.fromString("'" + MY_VALUE_SET_URL + "'", inputExpression);
    // Setup mocks
    when(terminologyService.intersect(any(), any())).thenReturn(setOfSimpleFrom(codeableConcept1, codeableConcept3, codeableConcept4));
    // Prepare the inputs to the function.
    final ParserContext parserContext = new ParserContextBuilder(spark, fhirContext).terminologyClientFactory(terminologyServiceFactory).build();
    final NamedFunctionInput memberOfInput = new NamedFunctionInput(parserContext, inputExpression, Collections.singletonList(argumentExpression));
    // Invoke the function.
    final FhirPath result = new MemberOfFunction().invoke(memberOfInput);
    final Dataset<Row> expectedResult = new DatasetBuilder(spark).withIdColumn().withColumn(DataTypes.BooleanType).withRow("diagnosticreport-1", true).withRow("diagnosticreport-2", false).withRow("diagnosticreport-3", true).withRow("diagnosticreport-4", true).withRow("diagnosticreport-5", false).withRow("diagnosticreport-6", true).withRow("diagnosticreport-7", null).build();
    // Check the result.
    assertTrue(result instanceof BooleanPath);
    assertThat((BooleanPath) result).hasExpression("DiagnosticReport.code.memberOf('" + MY_VALUE_SET_URL + "')").isSingular().hasFhirType(FHIRDefinedType.BOOLEAN).isElementPath(BooleanPath.class).selectOrderedResult().hasRows(expectedResult);
    verify(terminologyService).intersect(eq(MY_VALUE_SET_URL), eq(setOfSimpleFrom(coding1, coding2, coding3, coding4, coding5)));
    verifyNoMoreInteractions(terminologyService);
}
Also used : StringLiteralPath(au.csiro.pathling.fhirpath.literal.StringLiteralPath) FhirPath(au.csiro.pathling.fhirpath.FhirPath) BooleanPath(au.csiro.pathling.fhirpath.element.BooleanPath) ParserContextBuilder(au.csiro.pathling.test.builders.ParserContextBuilder) ElementPath(au.csiro.pathling.fhirpath.element.ElementPath) NamedFunctionInput(au.csiro.pathling.fhirpath.function.NamedFunctionInput) Coding(org.hl7.fhir.r4.model.Coding) SparkHelpers.rowFromCoding(au.csiro.pathling.test.helpers.SparkHelpers.rowFromCoding) ElementDefinition(au.csiro.pathling.fhirpath.element.ElementDefinition) Row(org.apache.spark.sql.Row) DatasetBuilder(au.csiro.pathling.test.builders.DatasetBuilder) ParserContext(au.csiro.pathling.fhirpath.parser.ParserContext) CodeableConcept(org.hl7.fhir.r4.model.CodeableConcept) SparkHelpers.rowFromCodeableConcept(au.csiro.pathling.test.helpers.SparkHelpers.rowFromCodeableConcept) ElementPathBuilder(au.csiro.pathling.test.builders.ElementPathBuilder) Test(org.junit.jupiter.api.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest)

Example 7 with BooleanPath

use of au.csiro.pathling.fhirpath.element.BooleanPath in project pathling by aehrc.

the class BooleansTestFunction method invoke.

@Nonnull
@Override
public FhirPath invoke(@Nonnull final NamedFunctionInput input) {
    checkNoArguments(type.getFunctionName(), input);
    final NonLiteralPath inputPath = input.getInput();
    checkUserInput(inputPath instanceof BooleanPath, "Input to " + type + " function must be Boolean");
    final Column inputColumn = inputPath.getValueColumn();
    final String expression = expressionFromInput(input, type.getFunctionName());
    final Column valueColumn = type.getEquality().apply(inputColumn);
    return buildAggregateResult(inputPath.getDataset(), input.getContext(), inputPath, valueColumn, expression);
}
Also used : BooleanPath(au.csiro.pathling.fhirpath.element.BooleanPath) Column(org.apache.spark.sql.Column) NonLiteralPath(au.csiro.pathling.fhirpath.NonLiteralPath) Nonnull(javax.annotation.Nonnull)

Example 8 with BooleanPath

use of au.csiro.pathling.fhirpath.element.BooleanPath in project pathling by aehrc.

the class IifFunction method invoke.

@Nonnull
@Override
public FhirPath invoke(@Nonnull final NamedFunctionInput input) {
    final NonLiteralPath inputPath = input.getInput();
    checkUserInput(input.getArguments().size() == 3, "3 arguments must be supplied to iif function");
    final FhirPath condition = input.getArguments().get(0);
    checkUserInput(condition instanceof BooleanPath, "Condition argument to iif must be Boolean: " + condition.getExpression());
    checkUserInput(condition.isSingular(), "Condition argument to iif must be singular: " + condition.getExpression());
    final BooleanPath conditionBoolean = (BooleanPath) condition;
    checkUserInput(conditionBoolean.getThisColumn().isPresent(), "Condition argument to iif function must be navigable from collection item (use $this): " + conditionBoolean.getExpression());
    // Join the three datasets together and create a value column.
    final FhirPath ifTrue = input.getArguments().get(1);
    final FhirPath otherwise = input.getArguments().get(2);
    final Dataset<Row> dataset = join(input.getContext(), Arrays.asList(conditionBoolean, ifTrue, otherwise), JoinType.LEFT_OUTER);
    final Column valueColumn = when(conditionBoolean.getValueColumn().equalTo(true), ifTrue.getValueColumn()).otherwise(otherwise.getValueColumn());
    // Build a new ElementPath based on the type of the literal `ifTrue` and `otherwise` arguments,
    // and populate it with the dataset and calculated value column.
    final String expression = expressionFromInput(input, NAME);
    return ifTrue.combineWith(otherwise, dataset, expression, inputPath.getIdColumn(), inputPath.getEidColumn(), valueColumn, inputPath.isSingular(), inputPath.getThisColumn());
}
Also used : FhirPath(au.csiro.pathling.fhirpath.FhirPath) BooleanPath(au.csiro.pathling.fhirpath.element.BooleanPath) Column(org.apache.spark.sql.Column) Row(org.apache.spark.sql.Row) NonLiteralPath(au.csiro.pathling.fhirpath.NonLiteralPath) Nonnull(javax.annotation.Nonnull)

Example 9 with BooleanPath

use of au.csiro.pathling.fhirpath.element.BooleanPath in project pathling by aehrc.

the class BooleanOperator method invoke.

@Nonnull
@Override
public FhirPath invoke(@Nonnull final OperatorInput input) {
    final FhirPath left = input.getLeft();
    final FhirPath right = input.getRight();
    checkUserInput(left instanceof BooleanPath || left instanceof BooleanLiteralPath, "Left operand to " + type + " operator must be Boolean: " + left.getExpression());
    checkUserInput(left.isSingular(), "Left operand to " + type + " operator must be singular: " + left.getExpression());
    checkUserInput(right instanceof BooleanPath || right instanceof BooleanLiteralPath, "Right operand to " + type + " operator must be Boolean: " + right.getExpression());
    checkUserInput(right.isSingular(), "Right operand to " + type + " operator must be singular: " + right.getExpression());
    final Column leftValue = left.getValueColumn();
    final Column rightValue = right.getValueColumn();
    // Based on the type of operator, create the correct column expression.
    final Column valueColumn;
    switch(type) {
        case AND:
            valueColumn = leftValue.and(rightValue);
            break;
        case OR:
            valueColumn = leftValue.or(rightValue);
            break;
        case XOR:
            valueColumn = when(leftValue.isNull().or(rightValue.isNull()), null).when(leftValue.equalTo(true).and(rightValue.equalTo(false)).or(leftValue.equalTo(false).and(rightValue.equalTo(true))), true).otherwise(false);
            break;
        case IMPLIES:
            valueColumn = when(leftValue.equalTo(true), rightValue).when(leftValue.equalTo(false), true).otherwise(when(rightValue.equalTo(true), true).otherwise(null));
            break;
        default:
            throw new AssertionError("Unsupported boolean operator encountered: " + type);
    }
    final String expression = left.getExpression() + " " + type + " " + right.getExpression();
    final Dataset<Row> dataset = join(input.getContext(), left, right, JoinType.LEFT_OUTER);
    final Column idColumn = left.getIdColumn();
    final Optional<Column> eidColumn = findEidColumn(left, right);
    final Optional<Column> thisColumn = findThisColumn(left, right);
    return ElementPath.build(expression, dataset, idColumn, eidColumn, valueColumn, true, Optional.empty(), thisColumn, FHIRDefinedType.BOOLEAN);
}
Also used : FhirPath(au.csiro.pathling.fhirpath.FhirPath) BooleanPath(au.csiro.pathling.fhirpath.element.BooleanPath) NonLiteralPath.findEidColumn(au.csiro.pathling.fhirpath.NonLiteralPath.findEidColumn) Column(org.apache.spark.sql.Column) NonLiteralPath.findThisColumn(au.csiro.pathling.fhirpath.NonLiteralPath.findThisColumn) Row(org.apache.spark.sql.Row) BooleanLiteralPath(au.csiro.pathling.fhirpath.literal.BooleanLiteralPath) Nonnull(javax.annotation.Nonnull)

Aggregations

BooleanPath (au.csiro.pathling.fhirpath.element.BooleanPath)9 FhirPath (au.csiro.pathling.fhirpath.FhirPath)7 Nonnull (javax.annotation.Nonnull)7 Column (org.apache.spark.sql.Column)7 Row (org.apache.spark.sql.Row)6 NonLiteralPath (au.csiro.pathling.fhirpath.NonLiteralPath)4 ParserContext (au.csiro.pathling.fhirpath.parser.ParserContext)4 BooleanLiteralPath (au.csiro.pathling.fhirpath.literal.BooleanLiteralPath)3 ResourcePath (au.csiro.pathling.fhirpath.ResourcePath)2 ElementDefinition (au.csiro.pathling.fhirpath.element.ElementDefinition)2 ElementPath (au.csiro.pathling.fhirpath.element.ElementPath)2 Parser (au.csiro.pathling.fhirpath.parser.Parser)2 DatasetBuilder (au.csiro.pathling.test.builders.DatasetBuilder)2 ElementPathBuilder (au.csiro.pathling.test.builders.ElementPathBuilder)2 ParserContextBuilder (au.csiro.pathling.test.builders.ParserContextBuilder)2 Nullable (javax.annotation.Nullable)2 Test (org.junit.jupiter.api.Test)2 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)2 DatasetWithColumn (au.csiro.pathling.QueryHelpers.DatasetWithColumn)1 NonLiteralPath.findEidColumn (au.csiro.pathling.fhirpath.NonLiteralPath.findEidColumn)1