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);
}
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);
}
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());
}
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);
}
Aggregations