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

dev.dsf.fhir.search.parameters.basic.AbstractNameOrAliasParameter Maven / Gradle / Ivy

package dev.dsf.fhir.search.parameters.basic;

import java.sql.Array;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;

import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.StringType;

import dev.dsf.fhir.function.BiFunctionWithSqlException;

public class AbstractNameOrAliasParameter extends AbstractStringParameter
{
	public static final String PARAMETER_NAME = "name";

	private final String resourceColumn;
	private final Predicate hasName;
	private final Function getName;
	private final Predicate hasAlias;
	private final Function> getAlias;

	public AbstractNameOrAliasParameter(Class resourceType, String resourceColumn, Predicate hasName,
			Function getName, Predicate hasAlias, Function> getAlias)
	{
		super(resourceType, PARAMETER_NAME);

		this.resourceColumn = resourceColumn;
		this.hasName = hasName;
		this.getName = getName;
		this.hasAlias = hasAlias;
		this.getAlias = getAlias;
	}

	@Override
	public String getFilterQuery()
	{
		return switch (valueAndType.type)
		{
			case STARTS_WITH,
					CONTAINS ->
				"(lower(" + resourceColumn
						+ "->>'name') LIKE ? OR EXISTS (SELECT 1 FROM (SELECT jsonb_array_elements_text("
						+ resourceColumn + "->'alias') AS alias) AS aliases WHERE alias LIKE ?))";

			case EXACT -> "(" + resourceColumn + "->>'name' = ? OR " + resourceColumn + "->'alias' ?? ?)";
		};
	}

	@Override
	public int getSqlParameterCount()
	{
		return 2;
	}

	@Override
	public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement,
			BiFunctionWithSqlException arrayCreator) throws SQLException
	{
		switch (valueAndType.type)
		{
			case STARTS_WITH:
				statement.setString(parameterIndex, valueAndType.value.toLowerCase() + "%");
				return;

			case CONTAINS:
				statement.setString(parameterIndex, "%" + valueAndType.value.toLowerCase() + "%");
				return;

			case EXACT:
				statement.setString(parameterIndex, valueAndType.value);
				return;
		}
	}

	@Override
	protected boolean resourceMatches(R resource)
	{
		return (hasName.test(resource) && nameMatches(getName.apply(resource)))
				|| (hasAlias.test(resource) && aliasMatches(resource));
	}

	private boolean aliasMatches(R resource)
	{
		return getAlias.apply(resource).stream().filter(StringType::hasValue).map(StringType::getValue)
				.anyMatch(this::nameMatches);
	}

	private boolean nameMatches(String name)
	{
		return switch (valueAndType.type)
		{
			case STARTS_WITH -> name.toLowerCase().startsWith(valueAndType.value.toLowerCase());
			case CONTAINS -> name.toLowerCase().contains(valueAndType.value.toLowerCase());
			case EXACT -> Objects.equals(name, valueAndType.value);
		};
	}

	@Override
	protected String getSortSql(String sortDirectionWithSpacePrefix)
	{
		return "(SELECT array_agg(name) FROM (SELECT " + resourceColumn
				+ "->>'name' AS name UNION SELECT jsonb_array_elements_text(" + resourceColumn
				+ "->'alias') AS name) AS names)" + sortDirectionWithSpacePrefix;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy