diff --git a/li.strolch.agent/src/main/java/li/strolch/search/SearchBuilder.java b/li.strolch.agent/src/main/java/li/strolch/search/SearchBuilder.java
index 31ce62100..ccc3b865a 100644
--- a/li.strolch.agent/src/main/java/li/strolch/search/SearchBuilder.java
+++ b/li.strolch.agent/src/main/java/li/strolch/search/SearchBuilder.java
@@ -2,6 +2,7 @@ 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 li.strolch.model.StrolchRootElement;
@@ -20,7 +21,7 @@ import org.slf4j.LoggerFactory;
*
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 param:<bagId>:<paramId>:<value>
adds search expression for given
+ * 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
@@ -79,39 +80,48 @@ public class SearchBuilder {
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();
- if (!part.startsWith("param:")) {
-
- if (se == null)
- se = (SearchExpression) id(containsIgnoreCase(part)).or(name(containsIgnoreCase(part)));
- else
- se = se.and((SearchExpression) id(containsIgnoreCase(part)).or(name(containsIgnoreCase(part))));
+ boolean negate = false;
+ if (part.startsWith("!")) {
+ negate = true;
+ part = part.substring(1);
+ }
+ String[] paramParts = part.split(":", -1);
+ if (paramParts.length != 3) {
+ se = add(and, negate, se, id(containsIgnoreCase(part)).or(name(containsIgnoreCase(part))));
} else {
- String[] paramParts = part.split(":");
- if (paramParts.length != 4) {
+ String bagId = paramParts[0];
+ String paramId = paramParts[1];
+ String value = paramParts[2];
- if (se == null)
- se = (SearchExpression) id(containsIgnoreCase(part)).or(name(containsIgnoreCase(part)));
- else
- se = se.and(
- (SearchExpression) id(containsIgnoreCase(part)).or(name(containsIgnoreCase(part))));
+ SearchPredicate predicate;
+ if (value.isEmpty())
+ predicate = isEqualTo(value);
+ else
+ predicate = containsIgnoreCase(value);
- } else {
-
- String bagId = paramParts[1];
- String paramId = paramParts[2];
- String value = paramParts[3];
-
- if (se == null)
- se = param(bagId, paramId, containsIgnoreCase(value));
- else
- se = se.and(param(bagId, paramId, containsIgnoreCase(value)));
- }
+ se = add(and, negate, se, param(bagId, paramId, predicate));
}
}
@@ -122,6 +132,21 @@ public class SearchBuilder {
return search;
}
+ private static SearchExpression add(boolean and, boolean negate,
+ SearchExpression se, SearchExpression expression) {
+
+ if (negate)
+ expression = expression.not();
+
+ if (se == null)
+ return expression;
+
+ if (and)
+ return se.and(expression);
+ else
+ return se.or(expression);
+ }
+
public static RootElementSearchResult orderBy(
RootElementSearchResult searchResult, String orderBy, boolean descending) {