li.strolch.search.SearchBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of agent Show documentation
Show all versions of agent Show documentation
Strolch Agent which is the runtime for Strolch
The newest version!
package li.strolch.search;
import static li.strolch.search.ExpressionsSupport.*;
import static li.strolch.search.PredicatesSupport.containsIgnoreCase;
import static li.strolch.search.PredicatesSupport.isEqualTo;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
import java.util.List;
import java.util.function.Function;
import li.strolch.model.ParameterBag;
import li.strolch.model.State;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.Tags;
import li.strolch.model.parameter.Parameter;
import li.strolch.utils.helper.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A helper class to build search expressions on {@link StrolchRootElement}
*
* This is often used in a web context where searches are performed on multiple parameters etc. of an element
*
* Note that the query string is parsed using the following rules:
*
* - query is trimmed
* - empty query means search for everything, i.e. no {@link SearchExpression SearchExpressions} are added
* - query is split by space, and each part is handled further:
* - format {@code param:
::} adds search expression for given
* bag/param
* - otherwise search expression for id and name are added
* - all added search expressions are ANDed
*
*/
public class SearchBuilder {
private static final Logger logger = LoggerFactory.getLogger(SearchBuilder.class);
/**
* Builds an {@link OrderSearch} for the given types with the given query
*
* @param query
* the query
* @param types
* the type of orders to search
*
* @return the {@link OrderSearch}
*/
public static OrderSearch buildOrderSearch(String query, String... types) {
return buildSearch(new OrderSearch().types(types), query);
}
/**
* Builds an {@link ResourceSearch} for the given types with the given query
*
* @param query
* the query
* @param types
* the type of resources to search
*
* @return the {@link OrderSearch}
*/
public static ResourceSearch buildResourceSearch(String query, String... types) {
return buildSearch(new ResourceSearch().types(types), query);
}
/**
* Builds an {@link ActivitySearch} for the given types with the given query
*
* @param query
* the query
* @param types
* the type of activities to search
*
* @return the {@link OrderSearch}
*/
public static ActivitySearch buildActivitySearch(String query, String... types) {
return buildSearch(new ActivitySearch().types(types), query);
}
public static ValueSearch buildSimpleValueSearch(ValueSearch search, String query,
List> extractors) {
if (extractors.isEmpty() || query == null)
return search;
query = query.trim();
if (query.isEmpty())
return search;
boolean negate = false;
if (query.startsWith("!")) {
negate = true;
query = query.substring(1);
}
String[] parts = query.split(" ");
ValueSearchExpression searchExpression = null;
for (String part : parts) {
ValueSearchExpression partSearchExpression = null;
for (Function extractor : extractors) {
if (partSearchExpression == null) {
partSearchExpression = ValueSearchExpressionBuilder.containsIgnoreCase(extractor, part);
} else {
partSearchExpression = partSearchExpression
.or(ValueSearchExpressionBuilder.containsIgnoreCase(extractor, part));
}
}
if (searchExpression == null) {
searchExpression = partSearchExpression;
} else {
searchExpression = searchExpression.and(partSearchExpression);
}
}
if (searchExpression != null) {
if (negate)
searchExpression = searchExpression.not();
search.where(searchExpression);
}
return search;
}
@SuppressWarnings("unchecked")
private static > U buildSearch(U search, String query) {
query = trimOrEmpty(query);
if (query.isEmpty())
return search;
boolean and = true;
if (query.startsWith("&")) {
query = query.substring(1);
} else if (query.startsWith("and ")) {
query = query.substring("and ".length());
} else if (query.startsWith("|")) {
and = false;
query = query.substring(1);
} else if (query.startsWith("or ")) {
and = false;
query = query.substring("or ".length());
}
query = trimOrEmpty(query);
SearchExpression se = null;
String[] parts = query.split(" ");
for (String part : parts) {
part = part.trim();
boolean negate = false;
if (part.startsWith("!")) {
negate = true;
part = part.substring(1);
}
String[] paramParts = parseParts(part);
if (paramParts.length != 3) {
SearchExpression expression;
if (part.startsWith("$state") && (search instanceof OrderSearch || search instanceof ActivitySearch)) {
part = part.substring("$state".length() + 1);
if (part.isEmpty() || State.parseAllowNull(part) == null) {
expression = id(containsIgnoreCase(part)).or(name(containsIgnoreCase(part)));
} else {
expression = state(isEqualTo(part));
}
} else {
expression = id(containsIgnoreCase(part)).or(name(containsIgnoreCase(part)));
}
se = add(and, negate, se, expression);
} else {
String bagId = paramParts[0];
String paramId = paramParts[1];
String value = paramParts[2];
SearchPredicate predicate;
if (value.isEmpty())
predicate = isEqualTo(value);
else
predicate = containsIgnoreCase(value);
if (!bagId.equals("?")) {
se = add(and, negate, se, param(bagId, paramId, predicate));
} else {
se = add(and, negate, se, element -> {
for (String b : element.getParameterBagKeySet()) {
ParameterBag bag = element.getParameterBag(b);
Parameter