Skip to content

Commit

Permalink
Extract and document filtering and projection functions
Browse files Browse the repository at this point in the history
  • Loading branch information
johngrimes committed Jul 1, 2024
1 parent 89e5e1a commit 7b3f4bf
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package au.csiro.pathling.fhirpath.function;

import au.csiro.pathling.fhirpath.TypeSpecifier;
import au.csiro.pathling.fhirpath.collection.Collection;
import au.csiro.pathling.fhirpath.validation.FhirPathFunction;
import javax.annotation.Nonnull;

/**
* Contains functions for filtering and projecting elements in a collection.
*
* @author Piotr Szul
* @author John Grimes
* @see <a href="https://build.fhir.org/ig/HL7/FHIRPath/#filtering-and-projection">FHIRPath
* Specification - Filtering and projection</a>
*/
public class FilteringAndProjectionFunctions {

/**
* Returns a collection containing only those elements in the input collection for which the
* stated criteria expression evaluates to {@code true}. Elements for which the expression
* evaluates to {@code false} or empty are not included in the result.
* <p>
* If the input collection is empty, the result is empty.
* <p>
* If the result of evaluating the condition is other than a single boolean value, the evaluation
* will end and signal an error to the calling environment, consistent with singleton evaluation
* of collections behavior.
*
* @param input The input collection
* @param expression The criteria expression
* @return A collection containing only those elements for which the criteria expression evaluates
* to {@code true}
* @see <a
* href="https://build.fhir.org/ig/HL7/FHIRPath/#wherecriteria--expression--collection">where</a>
*/
@FhirPathFunction
@Nonnull
public static Collection where(@Nonnull final Collection input,
@Nonnull final CollectionTransform expression) {
return input.filter(expression.requireBoolean().toColumnTransformation(input));
}

/**
* Returns a collection that contains all items in the input collection that are of the given type
* or a subclass thereof. If the input collection is empty, the result is empty. The type argument
* is an identifier that must resolve to the name of a type in a model. For implementations with
* compile-time typing, this requires special-case handling when processing the argument to treat
* it as type specifier rather than an identifier expression.
*
* @param input The input collection
* @param typeSpecifier The type specifier
* @return A collection containing only those elements that are of the specified type
* @see <a href="https://pathling.csiro.au/docs/fhirpath/functions.html#oftype">ofType</a>
*/
@FhirPathFunction
@Nonnull
public static Collection ofType(@Nonnull final Collection input,
@Nonnull final TypeSpecifier typeSpecifier) {
return input.filterByType(typeSpecifier);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import static java.util.Objects.nonNull;

import au.csiro.pathling.fhirpath.StringCoercible;
import au.csiro.pathling.fhirpath.TypeSpecifier;
import au.csiro.pathling.fhirpath.collection.BooleanCollection;
import au.csiro.pathling.fhirpath.collection.Collection;
import au.csiro.pathling.fhirpath.collection.EmptyCollection;
Expand All @@ -45,22 +44,6 @@ public class StandardFunctions {

public static final String REFERENCE_ELEMENT_NAME = "reference";

/**
* Describes a function which can scope down the previous invocation within a FHIRPath expression,
* based upon an expression passed in as an argument. Supports the use of `$this` to reference the
* element currently in scope.
*
* @param input the input collection
* @param expression the expression to evaluate
* @see <a href="https://pathling.csiro.au/docs/fhirpath/functions.html#where">where</a>
*/
@Nonnull
@FhirPathFunction
public static Collection where(@Nonnull final Collection input,
@Nonnull final CollectionTransform expression) {
return input.filter(expression.requireBoolean().toColumnTransformation(input));
}


// Maybe these too can be implemented as colum functions????
@FhirPathFunction
Expand Down Expand Up @@ -120,26 +103,13 @@ public static IntegerCollection count(@Nonnull final Collection input) {
public static Collection extension(@Nonnull final Collection input,
@Nonnull final StringCollection url) {
return input.traverse(EXTENSION_ELEMENT_NAME).map(extensionCollection ->
where(extensionCollection, c -> c.traverse(URL_ELEMENT_NAME).map(
FilteringAndProjectionFunctions.where(extensionCollection, c -> c.traverse(URL_ELEMENT_NAME).map(
urlCollection -> urlCollection.getComparison(EQUALS).apply(url))
.map(col -> BooleanCollection.build(new DefaultRepresentation(col)))
.orElse(BooleanCollection.fromValue(false)))
).orElse(EmptyCollection.getInstance());
}

/**
* A function filters items in the input collection to only those that are of the given type.
*
* @param input the input collection
* @param typeSpecifier the type specifier
* @see <a href="https://pathling.csiro.au/docs/fhirpath/functions.html#oftype">ofType</a>
*/
@FhirPathFunction
public static Collection ofType(@Nonnull final Collection input,
@Nonnull final TypeSpecifier typeSpecifier) {
return input.filterByType(typeSpecifier);
}

@FhirPathFunction
public static StringCollection join(@Nonnull final StringCollection input,
@Nullable final StringCollection separator) {
Expand All @@ -162,7 +132,7 @@ public static StringCollection join(@Nonnull final StringCollection input,
public static BooleanCollection exists(@Nonnull final Collection input,
@Nullable final CollectionTransform criteria) {
return BooleanLogicFunctions.not(empty(nonNull(criteria)
? where(input, criteria)
? FilteringAndProjectionFunctions.where(input, criteria)
: input));

}
Expand Down

0 comments on commit 7b3f4bf

Please sign in to comment.