use of au.csiro.pathling.fhirpath.NonLiteralPath in project pathling by aehrc.
the class WhereFunctionTest method whereOnResource.
// This test simulates the execution of the where function on the path
// `Patient.reverseResolve(Encounter.subject).where($this.status = 'in-progress')`.
@Test
void whereOnResource() {
final String statusColumn = randomAlias();
final Dataset<Row> inputDataset = new DatasetBuilder(spark).withIdColumn().withEidColumn().withIdColumn().withColumn(statusColumn, DataTypes.StringType).withRow("patient-1", makeEid(1), "encounter-1", "in-progress").withRow("patient-1", makeEid(0), "encounter-2", "finished").withRow("patient-2", makeEid(0), "encounter-3", "in-progress").withRow("patient-3", makeEid(1), "encounter-4", "in-progress").withRow("patient-3", makeEid(0), "encounter-5", "finished").withRow("patient-4", makeEid(1), "encounter-6", "finished").withRow("patient-4", makeEid(0), "encounter-7", "finished").withRow("patient-5", makeEid(1), "encounter-8", "in-progress").withRow("patient-5", makeEid(0), "encounter-9", "in-progress").withRow("patient-6", null, null, null).build();
final ResourcePath inputPath = new ResourcePathBuilder(spark).expression("reverseResolve(Encounter.subject)").dataset(inputDataset).idEidAndValueColumns().buildCustom();
// Build an expression which represents the argument to the function. We assume that the value
// column from the input dataset is also present within the argument dataset.
final NonLiteralPath thisPath = inputPath.toThisPath();
final Dataset<Row> argumentDataset = thisPath.getDataset().withColumn("value", thisPath.getDataset().col(statusColumn).equalTo("in-progress"));
assertTrue(thisPath.getThisColumn().isPresent());
final ElementPath argumentPath = new ElementPathBuilder(spark).fhirType(FHIRDefinedType.BOOLEAN).dataset(argumentDataset).idColumn(inputPath.getIdColumn()).valueColumn(argumentDataset.col("value")).thisColumn(thisPath.getThisColumn().get()).singular(true).build();
// Prepare the input to the function.
final ParserContext parserContext = new ParserContextBuilder(spark, fhirContext).build();
final NamedFunctionInput whereInput = new NamedFunctionInput(parserContext, inputPath, Collections.singletonList(argumentPath));
// Execute the function.
final NamedFunction whereFunction = NamedFunction.getInstance("where");
final FhirPath result = whereFunction.invoke(whereInput);
// Check the result dataset.
final Dataset<Row> expectedDataset = new DatasetBuilder(spark).withIdColumn().withEidColumn().withIdColumn().withRow("patient-1", makeEid(0), null).withRow("patient-1", makeEid(1), "patient-1").withRow("patient-2", makeEid(0), "patient-2").withRow("patient-3", makeEid(0), null).withRow("patient-3", makeEid(1), "patient-3").withRow("patient-4", makeEid(0), null).withRow("patient-4", makeEid(1), null).withRow("patient-5", makeEid(0), "patient-5").withRow("patient-5", makeEid(1), "patient-5").withRow("patient-6", null, null).build();
assertThat(result).selectOrderedResultWithEid().hasRows(expectedDataset);
}
use of au.csiro.pathling.fhirpath.NonLiteralPath in project pathling by aehrc.
the class WhereFunctionTest method whereOnElement.
@Test
void whereOnElement() {
// Build an expression which represents the input to the function.
final Dataset<Row> dataset = new DatasetBuilder(spark).withIdColumn().withEidColumn().withColumn(DataTypes.StringType).withRow("patient-1", makeEid(1), "en").withRow("patient-1", makeEid(0), "es").withRow("patient-2", makeEid(0), "de").withRow("patient-3", makeEid(2), "en").withRow("patient-3", makeEid(1), "en").withRow("patient-3", makeEid(0), "zh").withRow("patient-4", makeEid(1), "fr").withRow("patient-4", makeEid(0), "fr").withRow("patient-5", null, null).build();
final ElementPath inputPath = new ElementPathBuilder(spark).fhirType(FHIRDefinedType.STRING).dataset(dataset).idAndEidAndValueColumns().singular(false).build();
final NonLiteralPath thisPath = inputPath.toThisPath();
// Build an expression which represents the argument to the function.
final Dataset<Row> argumentDataset = thisPath.getDataset().withColumn("value", inputPath.getValueColumn().equalTo("en"));
assertTrue(thisPath.getThisColumn().isPresent());
final ElementPath argumentExpression = new ElementPathBuilder(spark).fhirType(FHIRDefinedType.BOOLEAN).dataset(argumentDataset).idColumn(inputPath.getIdColumn()).valueColumn(argumentDataset.col("value")).thisColumn(thisPath.getThisColumn().get()).singular(true).build();
// Prepare the input to the function.
final ParserContext parserContext = new ParserContextBuilder(spark, fhirContext).build();
final NamedFunctionInput whereInput = new NamedFunctionInput(parserContext, inputPath, Collections.singletonList(argumentExpression));
// Execute the function.
final NamedFunction whereFunction = NamedFunction.getInstance("where");
final FhirPath result = whereFunction.invoke(whereInput);
// Check the result dataset.
final Dataset<Row> expectedDataset = new DatasetBuilder(spark).withIdColumn().withEidColumn().withColumn(DataTypes.StringType).withRow("patient-1", makeEid(0), null).withRow("patient-1", makeEid(1), "en").withRow("patient-2", makeEid(0), null).withRow("patient-3", makeEid(0), null).withRow("patient-3", makeEid(1), "en").withRow("patient-3", makeEid(2), "en").withRow("patient-4", makeEid(0), null).withRow("patient-4", makeEid(1), null).withRow("patient-5", null, null).build();
assertThat(result).selectOrderedResultWithEid().hasRows(expectedDataset);
}
use of au.csiro.pathling.fhirpath.NonLiteralPath in project pathling by aehrc.
the class QueryHelpers method join.
/**
* Joins any number of {@link FhirPath} expressions, using equality between their respective
* resource ID columns.
*
* @param parserContext the current {@link ParserContext}
* @param fhirPaths a list of {@link FhirPath} expressions
* @param joinType a {@link JoinType}
* @return a new {@link Dataset}
*/
@Nonnull
public static Dataset<Row> join(@Nonnull final ParserContext parserContext, @Nonnull final List<FhirPath> fhirPaths, @Nonnull final JoinType joinType) {
checkArgument(fhirPaths.size() > 1, "fhirPaths must contain more than one FhirPath");
final FhirPath left = fhirPaths.get(0);
final List<FhirPath> joinTargets = fhirPaths.subList(1, fhirPaths.size());
// Only non-literal paths will trigger a join.
final List<FhirPath> nonLiteralTargets = joinTargets.stream().filter(t -> t instanceof NonLiteralPath).collect(Collectors.toList());
if (left instanceof NonLiteralPath && nonLiteralTargets.isEmpty()) {
// to join.
return left.getDataset();
} else if (left instanceof LiteralPath && !nonLiteralTargets.isEmpty()) {
// right without any need to join.
return nonLiteralTargets.get(0).getDataset();
}
Dataset<Row> dataset = left.getDataset();
final List<Column> groupingColumns = parserContext.getGroupingColumns();
final Column idColumn = parserContext.getInputContext().getIdColumn();
final List<Column> leftColumns = checkColumnsAndFallback(left.getDataset(), groupingColumns, idColumn);
for (final FhirPath right : nonLiteralTargets) {
final List<Column> resolvedGroupingColumns = checkColumnsAndFallback(right.getDataset(), leftColumns, idColumn);
dataset = join(dataset, resolvedGroupingColumns, right.getDataset(), resolvedGroupingColumns, joinType);
}
return dataset;
}
use of au.csiro.pathling.fhirpath.NonLiteralPath in project pathling by aehrc.
the class WhereFunctionTest method nullValuesAreNull.
@Test
void nullValuesAreNull() {
// Build an expression which represents the input to the function.
final Dataset<Row> dataset = new DatasetBuilder(spark).withIdColumn().withEidColumn().withColumn(DataTypes.StringType).withRow("patient-1", makeEid(0), "en").withRow("patient-1", makeEid(1), "es").withRow("patient-2", makeEid(0), "de").withRow("patient-3", makeEid(0), "en").withRow("patient-3", makeEid(1), "en").withRow("patient-3", makeEid(2), "zh").withRow("patient-4", makeEid(0), "ar").build();
final ElementPath inputPath = new ElementPathBuilder(spark).fhirType(FHIRDefinedType.STRING).dataset(dataset).idAndEidAndValueColumns().singular(false).build();
// Build an expression which represents the argument to the function.
final NonLiteralPath thisPath = inputPath.toThisPath();
final Dataset<Row> argumentDataset = thisPath.getDataset().withColumn("value", functions.when(inputPath.getValueColumn().equalTo("en"), null).otherwise(true));
assertTrue(thisPath.getThisColumn().isPresent());
final ElementPath argumentPath = new ElementPathBuilder(spark).fhirType(FHIRDefinedType.BOOLEAN).dataset(argumentDataset).idColumn(inputPath.getIdColumn()).valueColumn(argumentDataset.col("value")).thisColumn(thisPath.getThisColumn().get()).singular(true).build();
// Prepare the input to the function.
final ParserContext parserContext = new ParserContextBuilder(spark, fhirContext).build();
final NamedFunctionInput whereInput = new NamedFunctionInput(parserContext, inputPath, Collections.singletonList(argumentPath));
// Execute the function.
final NamedFunction whereFunction = NamedFunction.getInstance("where");
final FhirPath result = whereFunction.invoke(whereInput);
// Check the result dataset.
final Dataset<Row> expectedDataset = new DatasetBuilder(spark).withIdColumn().withEidColumn().withColumn(DataTypes.StringType).withRow("patient-1", makeEid(0), null).withRow("patient-1", makeEid(1), "es").withRow("patient-2", makeEid(0), "de").withRow("patient-3", makeEid(0), null).withRow("patient-3", makeEid(1), null).withRow("patient-3", makeEid(2), "zh").withRow("patient-4", makeEid(0), "ar").build();
assertThat(result).selectOrderedResultWithEid().hasRows(expectedDataset);
}
use of au.csiro.pathling.fhirpath.NonLiteralPath in project pathling by aehrc.
the class IifFunctionTest method throwsErrorWithUntypedResourceAndLiteralResults.
@Test
void throwsErrorWithUntypedResourceAndLiteralResults() {
final NonLiteralPath condition = new ElementPathBuilder(spark).fhirType(FHIRDefinedType.BOOLEAN).expression("valueBoolean").singular(true).build().toThisPath();
final UntypedResourcePath ifTrue = new UntypedResourcePathBuilder(spark).expression("someUntypedResource").build();
final StringLiteralPath otherwise = StringLiteralPath.fromString("foo", condition);
final NamedFunctionInput iifInput = new NamedFunctionInput(parserContext, condition, Arrays.asList(condition, ifTrue, otherwise));
final NamedFunction notFunction = NamedFunction.getInstance("iif");
final InvalidUserInputError error = assertThrows(InvalidUserInputError.class, () -> notFunction.invoke(iifInput));
assertEquals("Paths cannot be merged into a collection together: someUntypedResource, 'foo'", error.getMessage());
}
Aggregations