All Downloads are FREE. Search and download functionalities are using the official Maven repository.

au.csiro.pathling.aggregate.DrillDownBuilder Maven / Gradle / Ivy

There is a newer version: 7.0.1
Show newest version
/*
 * Copyright 2023 Commonwealth Scientific and Industrial Research
 * Organisation (CSIRO) ABN 41 687 119 230.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package au.csiro.pathling.aggregate;

import static au.csiro.pathling.utilities.Preconditions.checkArgument;
import static au.csiro.pathling.utilities.Strings.parentheses;

import au.csiro.pathling.fhirpath.FhirPath;
import au.csiro.pathling.fhirpath.literal.LiteralPath;
import au.csiro.pathling.utilities.Strings;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.hl7.fhir.r4.model.Type;

/**
 * Builds FHIRPath expressions for retrieving the resources that are members of a grouping returned
 * by the "aggregate" operation.
 *
 * @author John Grimes
 */
public class DrillDownBuilder {

  @Nonnull
  private final List> labels;

  @Nonnull
  private final List groupings;

  @Nonnull
  private final Collection filters;

  /**
   * @param labels The labels from the subject grouping
   * @param groupings The grouping expressions from the request
   * @param filters The filters from the request
   */
  public DrillDownBuilder(@Nonnull final List> labels,
      @Nonnull final List groupings, @Nonnull final Collection filters) {
    checkArgument(labels.size() == groupings.size(), "Labels should be same size as groupings");
    this.labels = labels;
    this.groupings = groupings;
    this.filters = filters;
  }

  /**
   * Generates the FHIRPath string.
   *
   * @return A FHIRPath expression, unless there are no groupings or filters
   */
  @Nonnull
  public Optional build() {
    // We use a Set here to avoid situations where we needlessly have the same condition in the
    // expression more than once.
    final Collection fhirPaths = new LinkedHashSet<>();

    // Add each of the grouping expressions, along with either equality or contains against the
    // group value to convert it in to a Boolean expression.
    addGroupings(fhirPaths);

    // Add each of the filter expressions.
    addFilters(fhirPaths);

    // If there is more than one expression, wrap each expression in parentheses before joining
    // together with Boolean AND operators.
    return fhirPaths.size() > 0
           ? Optional.of(String.join(" and ", parenthesiseExpressions(fhirPaths)))
           : Optional.empty();
  }

  private void addGroupings(final Collection fhirPaths) {
    for (int i = 0; i < groupings.size(); i++) {
      final FhirPath grouping = groupings.get(i);
      final Optional label = labels.get(i);
      if (label.isPresent()) {
        final String literal = LiteralPath
            .expressionFor(grouping.getDataset(), grouping.getIdColumn(), label.get());
        final String equality = grouping.isSingular()
                                ? " = "
                                : " contains ";
        // We need to add parentheses around the grouping expression, as some expressions will not
        // play well with the equality or membership operator due to precedence.
        final String expression = literal.equals("true") && grouping.isSingular()
                                  ? grouping.getExpression()
                                  : parentheses(grouping.getExpression()) + equality + literal;
        fhirPaths.add(expression);
      } else {
        fhirPaths.add(parentheses(grouping.getExpression()) + ".empty()");
      }
    }
  }

  private void addFilters(@Nonnull final Collection fhirPaths) {
    final List filterExpressions = filters.stream()
        .map(FhirPath::getExpression)
        .collect(Collectors.toList());
    fhirPaths.addAll(filterExpressions);
  }

  @Nonnull
  private List parenthesiseExpressions(@Nonnull final Collection fhirPaths) {
    if (fhirPaths.size() > 1) {
      return fhirPaths.stream()
          .map(Strings::parentheses)
          .collect(Collectors.toList());
    } else {
      return new ArrayList<>(fhirPaths);
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy