
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