package io.ebeaninternal.server.expression;

import io.ebean.CacheMode;
import io.ebean.CountDistinctOrder;
import io.ebean.DtoQuery;
import io.ebean.Expression;
import io.ebean.ExpressionFactory;
import io.ebean.ExpressionList;
import io.ebean.FetchGroup;
import io.ebean.FetchPath;
import io.ebean.FutureIds;
import io.ebean.FutureList;
import io.ebean.FutureRowCount;
import io.ebean.Junction;
import io.ebean.OrderBy;
import io.ebean.PagedList;
import io.ebean.Pairs;
import io.ebean.Query;
import io.ebean.QueryIterator;
import io.ebean.Transaction;
import io.ebean.UpdateQuery;
import io.ebean.Version;
import io.ebean.event.BeanQueryRequest;
import io.ebean.search.Match;
import io.ebean.search.MultiMatch;
import io.ebean.search.TextCommonTerms;
import io.ebean.search.TextQueryString;
import io.ebean.search.TextSimple;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionList;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.SpiExpressionValidation;
import io.ebeaninternal.api.SpiJunction;
import io.ebeaninternal.server.deploy.BeanDescriptor;

import java.io.IOException;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;

Default implementation of ExpressionList.
/** * Default implementation of ExpressionList. */
public class DefaultExpressionList<T> implements SpiExpressionList<T> { private static final String AND = " and "; protected List<SpiExpression> list; protected final Query<T> query; private final ExpressionList<T> parentExprList; protected final ExpressionFactory expr; String allDocNestedPath;
Set to true for the "Text" root expression list.
/** * Set to true for the "Text" root expression list. */
private final boolean textRoot;
Construct for Text root expression list - this handles implicit Bool Should, Must etc.
/** * Construct for Text root expression list - this handles implicit Bool Should, Must etc. */
public DefaultExpressionList(Query<T> query) { this(query, query.getExpressionFactory(), null, new ArrayList<>(), true); } public DefaultExpressionList(Query<T> query, ExpressionList<T> parentExprList) { this(query, query.getExpressionFactory(), parentExprList); } DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList) { this(query, expr, parentExprList, new ArrayList<>()); } DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList, List<SpiExpression> list) { this(query, expr, parentExprList, list, false); } private DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList, List<SpiExpression> list, boolean textRoot) { this.textRoot = textRoot; this.list = list; this.query = query; this.expr = expr; this.parentExprList = parentExprList; } private DefaultExpressionList() { this(null, null, null, new ArrayList<>()); }
Wrap the expression list as a Junction or top level DefaultExpressionList.
Params:
  • list – The list of expressions grouped by nested path
  • nestedPath – The doc store nested path
  • type – The junction type (or null for top level expression list).
Returns:A single SpiExpression that has the nestedPath set
/** * Wrap the expression list as a Junction or top level DefaultExpressionList. * * @param list The list of expressions grouped by nested path * @param nestedPath The doc store nested path * @param type The junction type (or null for top level expression list). * @return A single SpiExpression that has the nestedPath set */
SpiExpression wrap(List<SpiExpression> list, String nestedPath, Junction.Type type) { DefaultExpressionList<T> wrapper = new DefaultExpressionList<>(query, expr, null, list, false); wrapper.setAllDocNested(nestedPath); if (type != null) { return new JunctionExpression<>(type, wrapper); } else { return wrapper; } } void simplifyEntries() { for (SpiExpression element : list) { element.simplify(); } } @Override public Junction<T> toJunction() { return new JunctionExpression<>(Junction.Type.FILTER, this); } @Override public boolean naturalKey(NaturalKeyQueryData<?> data) { // can't use naturalKey cache return false; } @Override public void simplify() { simplifyEntries(); }
Write being aware if it is the Top level "text" expressions.

If this is the Top level "text" expressions then it detects if explicit or implicit Bool Should, Must etc is required to wrap the expressions.

If implicit Bool is required SHOULD is used.

/** * Write being aware if it is the Top level "text" expressions. * <p> * If this is the Top level "text" expressions then it detects if explicit or implicit Bool Should, Must etc is required * to wrap the expressions. * </p> * <p> * If implicit Bool is required SHOULD is used. * </p> */
@Override public void writeDocQuery(DocQueryContext context) throws IOException { if (!textRoot) { writeDocQuery(context, null); } else { // this is a Top level "text" expressions so we may need to wrap in Bool SHOULD etc. if (list.isEmpty()) { throw new IllegalStateException("empty expression list?"); } if (allDocNestedPath != null) { context.startNested(allDocNestedPath); } int size = list.size(); SpiExpression first = list.get(0); boolean explicitBool = first instanceof SpiJunction<?>; boolean implicitBool = !explicitBool && size > 1; if (implicitBool || explicitBool) { context.startBoolGroup(); } if (implicitBool) { context.startBoolGroupList(Junction.Type.SHOULD); } for (SpiExpression expr : list) { if (explicitBool) { try { ((SpiJunction<?>) expr).writeDocQueryJunction(context); } catch (ClassCastException e) { throw new IllegalStateException("The top level text() expressions should be all be 'Must', 'Should' or 'Must Not' or none of them should be.", e); } } else { expr.writeDocQuery(context); } } if (implicitBool) { context.endBoolGroupList(); } if (implicitBool || explicitBool) { context.endBoolGroup(); } if (allDocNestedPath != null) { context.endNested(); } } } @Override public void writeDocQuery(DocQueryContext context, SpiExpression idEquals) throws IOException { if (allDocNestedPath != null) { context.startNested(allDocNestedPath); } int size = list.size(); if (size == 1 && idEquals == null) { // only 1 expression - skip bool list.get(0).writeDocQuery(context); } else if (size == 0 && idEquals != null) { // only idEquals - skip bool idEquals.writeDocQuery(context); } else { // bool must wrap all the children context.startBoolMust(); if (idEquals != null) { idEquals.writeDocQuery(context); } for (SpiExpression aList : list) { aList.writeDocQuery(context); } context.endBool(); } if (allDocNestedPath != null) { context.endNested(); } } @Override public SpiExpressionList<?> trimPath(int prefixTrim) { throw new IllegalStateException("Only allowed on FilterExpressionList"); } public List<SpiExpression> internalList() { return list; }
Return a copy of the expression list.

Each of the expressions are expected to be immutable and safe to reference.

/** * Return a copy of the expression list. * <p> * Each of the expressions are expected to be immutable and safe to reference. * </p> */
public DefaultExpressionList<T> copy(Query<T> query) { DefaultExpressionList<T> copy = new DefaultExpressionList<>(query, expr, null); copy.list.addAll(list); return copy; } @Override public DefaultExpressionList<T> copyForPlanKey() { DefaultExpressionList<T> copy = new DefaultExpressionList<>(); for (int i = 0; i < list.size(); i++) { copy.list.add(list.get(i).copyForPlanKey()); } return copy; } @Override public Object getIdEqualTo(String idName) { // always return null for this expression return null; }
Return true if one of the expressions is related to a Many property.
/** * Return true if one of the expressions is related to a Many property. */
@Override public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) { for (SpiExpression aList : list) { aList.containsMany(desc, whereManyJoins); } } @Override public void validate(SpiExpressionValidation validation) { for (SpiExpression aList : list) { aList.validate(validation); } } @Override public Query<T> query() { return query; } @Override public Query<T> asOf(Timestamp asOf) { return query.asOf(asOf); } @Override public Query<T> asDraft() { return query.asDraft(); } @Override public <D> DtoQuery<D> asDto(Class<D> dtoClass) { return query.asDto(dtoClass); } @Override public UpdateQuery<T> asUpdate() { return query.asUpdate(); } @Override public Query<T> setIncludeSoftDeletes() { return query.setIncludeSoftDeletes(); } @Override public List<Version<T>> findVersions() { return query.findVersions(); } @Override public List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end) { return query.findVersionsBetween(start, end); } @Override public ExpressionList<T> where() { return query.where(); } @Override public OrderBy<T> order() { return query.order(); } @Override public OrderBy<T> orderBy() { return query.order(); } @Override public ExpressionList<T> order(String orderByClause) { query.order(orderByClause); return this; } @Override public ExpressionList<T> orderBy(String orderBy) { query.order(orderBy); return this; } @Override public Query<T> setOrderBy(String orderBy) { return query.order(orderBy); } @Override public Query<T> orderById(boolean orderById) { return query.orderById(orderById); } @Override public Query<T> apply(FetchPath fetchPath) { return query.apply(fetchPath); } @Override public Query<T> usingTransaction(Transaction transaction) { return query.usingTransaction(transaction); } @Override public Query<T> usingConnection(Connection connection) { return query.usingConnection(connection); } @Override public int delete() { return query.delete(); } @Override public int delete(Transaction transaction) { return query.delete(transaction); } @Override public int update() { return query.update(); } @Override public int update(Transaction transaction) { return query.update(transaction); } @Override public FutureIds<T> findFutureIds() { return query.findFutureIds(); } @Override public FutureRowCount<T> findFutureCount() { return query.findFutureCount(); } @Override public FutureList<T> findFutureList() { return query.findFutureList(); } @Override public PagedList<T> findPagedList() { return query.findPagedList(); } @Override public int findCount() { return query.findCount(); } @Override public <A> List<A> findIds() { return query.findIds(); } @Override public QueryIterator<T> findIterate() { return query.findIterate(); } @Override public void findEach(Consumer<T> consumer) { query.findEach(consumer); } @Override public void findEachWhile(Predicate<T> consumer) { query.findEachWhile(consumer); } @Override public List<T> findList() { return query.findList(); } @Override public Set<T> findSet() { return query.findSet(); } @Override public <K> Map<K, T> findMap() { return query.findMap(); } @Override public <A> List<A> findSingleAttributeList() { return query.findSingleAttributeList(); } @Override public boolean exists() { return query.exists(); } @Override public T findOne() { return query.findOne(); } @Override public Optional<T> findOneOrEmpty() { return query.findOneOrEmpty(); } @Override public ExpressionList<T> filterMany(String manyProperty) { return query.filterMany(manyProperty); } @Override public ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params) { return query.filterMany(manyProperty).where(expressions, params); } @Override public Query<T> withLock(Query.LockType lockType) { return query.withLock(lockType); } @Override public Query<T> withLock(Query.LockType lockType, Query.LockWait lockWait) { return query.withLock(lockType, lockWait); } @Override public Query<T> forUpdate() { return query.forUpdate(); } @Override public Query<T> forUpdate(Query.LockType lockType) { return query.forUpdate(lockType); } @Override public Query<T> forUpdateNoWait() { return query.forUpdateNoWait(); } @Override public Query<T> forUpdateNoWait(Query.LockType lockType) { return query.forUpdateNoWait(lockType); } @Override public Query<T> forUpdateSkipLocked() { return query.forUpdateSkipLocked(); } @Override public Query<T> forUpdateSkipLocked(Query.LockType lockType) { return query.forUpdateSkipLocked(lockType); } @Override public Query<T> select(String fetchProperties) { return query.select(fetchProperties); } @Override public Query<T> select(FetchGroup<T> fetchGroup) { return query.select(fetchGroup); } @Override public Query<T> setDistinct(boolean distinct) { return query.setDistinct(distinct); } @Override public Query<T> setDocIndexName(String indexName) { return query.setDocIndexName(indexName); } @Override public ExpressionList<T> setFirstRow(int firstRow) { query.setFirstRow(firstRow); return this; } @Override public ExpressionList<T> setMaxRows(int maxRows) { query.setMaxRows(maxRows); return this; } @Override public Query<T> setMapKey(String mapKey) { return query.setMapKey(mapKey); } @Override public Query<T> setUseCache(boolean useCache) { return query.setUseCache(useCache); } @Override public Query<T> setBeanCacheMode(CacheMode useCache) { return query.setBeanCacheMode(useCache); } @Override public Query<T> setUseQueryCache(CacheMode useCache) { return query.setUseQueryCache(useCache); } @Override public Query<T> setCountDistinct(CountDistinctOrder orderBy) { return query.setCountDistinct(orderBy); } @Override public Query<T> setUseDocStore(boolean useDocsStore) { return query.setUseDocStore(useDocsStore); } @Override public Query<T> setDisableLazyLoading(boolean disableLazyLoading) { return query.setDisableLazyLoading(disableLazyLoading); } @Override public Query<T> setDisableReadAuditing() { return query.setDisableReadAuditing(); } @Override public Query<T> setLabel(String label) { return query.setLabel(label); } @Override public ExpressionList<T> having() { return query.having(); } @Override public ExpressionList<T> add(Expression expr) { list.add((SpiExpression) expr); return this; } @Override public ExpressionList<T> addAll(ExpressionList<T> exprList) { SpiExpressionList<T> spiList = (SpiExpressionList<T>) exprList; list.addAll(spiList.getUnderlyingList()); return this; } @Override public List<SpiExpression> getUnderlyingList() { return list; } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public void addSql(SpiExpressionRequest request) { for (int i = 0, size = list.size(); i < size; i++) { SpiExpression expression = list.get(i); if (i > 0) { request.append(AND); } expression.addSql(request); } } @Override public void addBindValues(SpiExpressionRequest request) { for (SpiExpression aList : list) { aList.addBindValues(request); } } @Override public void prepareExpression(BeanQueryRequest<?> request) { for (SpiExpression aList : list) { aList.prepareExpression(request); } }
Calculate a hash based on the expressions but excluding the actual bind values.
/** * Calculate a hash based on the expressions but excluding the actual bind * values. */
@Override public void queryPlanHash(StringBuilder builder) { builder.append("List["); if (textRoot) { builder.append("textRoot:true "); } if (allDocNestedPath != null) { builder.append("path:").append(allDocNestedPath).append(" "); } for (SpiExpression aList : list) { aList.queryPlanHash(builder); builder.append(","); } builder.append("]"); }
Calculate a hash based on the expressions.
/** * Calculate a hash based on the expressions. */
@Override public int queryBindHash() { int hash = DefaultExpressionList.class.getName().hashCode(); for (SpiExpression aList : list) { hash = hash * 92821 + aList.queryBindHash(); } return hash; } @Override public boolean isSameByBind(SpiExpression other) { DefaultExpressionList<?> that = (DefaultExpressionList<?>) other; if (list.size() != that.list.size()) { return false; } for (int i = 0, size = list.size(); i < size; i++) { if (!list.get(i).isSameByBind(that.list.get(i))) { return false; } } return true; }
Path exists - for the given path in a JSON document.
/** * Path exists - for the given path in a JSON document. */
@Override public ExpressionList<T> jsonExists(String propertyName, String path) { return add(expr.jsonExists(propertyName, path)); }
Path does not exist - for the given path in a JSON document.
/** * Path does not exist - for the given path in a JSON document. */
@Override public ExpressionList<T> jsonNotExists(String propertyName, String path) { return add(expr.jsonNotExists(propertyName, path)); }
Equal to expression for the value at the given path in the JSON document.
/** * Equal to expression for the value at the given path in the JSON document. */
@Override public ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value) { return add(expr.jsonEqualTo(propertyName, path, value)); }
Not Equal to - for the given path in a JSON document.
/** * Not Equal to - for the given path in a JSON document. */
@Override public ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object val) { return add(expr.jsonNotEqualTo(propertyName, path, val)); }
Greater than - for the given path in a JSON document.
/** * Greater than - for the given path in a JSON document. */
@Override public ExpressionList<T> jsonGreaterThan(String propertyName, String path, Object val) { return add(expr.jsonGreaterThan(propertyName, path, val)); }
Greater than or equal to - for the given path in a JSON document.
/** * Greater than or equal to - for the given path in a JSON document. */
@Override public ExpressionList<T> jsonGreaterOrEqual(String propertyName, String path, Object val) { return add(expr.jsonGreaterOrEqual(propertyName, path, val)); }
Less than - for the given path in a JSON document.
/** * Less than - for the given path in a JSON document. */
@Override public ExpressionList<T> jsonLessThan(String propertyName, String path, Object val) { return add(expr.jsonLessThan(propertyName, path, val)); }
Less than or equal to - for the given path in a JSON document.
/** * Less than or equal to - for the given path in a JSON document. */
@Override public ExpressionList<T> jsonLessOrEqualTo(String propertyName, String path, Object val) { return add(expr.jsonLessOrEqualTo(propertyName, path, val)); }
Between - for the given path in a JSON document.
/** * Between - for the given path in a JSON document. */
@Override public ExpressionList<T> jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue) { return add(expr.jsonBetween(propertyName, path, lowerValue, upperValue)); } @Override public ExpressionList<T> where(String expressions, Object... params) { expr.where(this, expressions, params); return this; } @Override public ExpressionList<T> bitwiseAny(String propertyName, long flags) { return add(expr.bitwiseAny(propertyName, flags)); } @Override public ExpressionList<T> bitwiseNot(String propertyName, long flags) { return add(expr.bitwiseAnd(propertyName, flags, 0)); } @Override public ExpressionList<T> bitwiseAll(String propertyName, long flags) { return add(expr.bitwiseAll(propertyName, flags)); } @Override public ExpressionList<T> bitwiseAnd(String propertyName, long flags, long match) { return add(expr.bitwiseAnd(propertyName, flags, match)); } @Override public ExpressionList<T> eq(String propertyName, Object value) { return add(expr.eq(propertyName, value)); } @Override public ExpressionList<T> eqOrNull(String propertyName, Object value) { return add(expr.eqOrNull(propertyName, value)); } @Override public ExpressionList<T> ieq(String propertyName, String value) { return add(expr.ieq(propertyName, value)); } @Override public ExpressionList<T> ine(String propertyName, String value) { return add(expr.ine(propertyName, value)); } @Override public ExpressionList<T> ne(String propertyName, Object value) { return add(expr.ne(propertyName, value)); } @Override public ExpressionList<T> allEq(Map<String, Object> propertyMap) { return add(expr.allEq(propertyMap)); } @Override public ExpressionList<T> and(Expression expOne, Expression expTwo) { return add(expr.and(expOne, expTwo)); } @Override public ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value) { return add(expr.inRangeWith(lowProperty, highProperty, value)); } @Override public ExpressionList<T> inRange(String propertyName, Object value1, Object value2) { return add(expr.inRange(propertyName, value1, value2)); } @Override public ExpressionList<T> between(String propertyName, Object value1, Object value2) { return add(expr.between(propertyName, value1, value2)); } @Override public ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value) { return add(expr.betweenProperties(lowProperty, highProperty, value)); } @Override public ExpressionList<T> contains(String propertyName, String value) { return add(expr.contains(propertyName, value)); } @Override public ExpressionList<T> endsWith(String propertyName, String value) { return add(expr.endsWith(propertyName, value)); } @Override public ExpressionList<T> ge(String propertyName, Object value) { add(expr.ge(propertyName, value)); return this; } @Override public ExpressionList<T> gt(String propertyName, Object value) { return add(expr.gt(propertyName, value)); } @Override public ExpressionList<T> gtOrNull(String propertyName, Object value) { add(expr.gtOrNull(propertyName, value)); return this; } @Override public ExpressionList<T> geOrNull(String propertyName, Object value) { add(expr.geOrNull(propertyName, value)); return this; } @Override public ExpressionList<T> icontains(String propertyName, String value) { return add(expr.icontains(propertyName, value)); } @Override public ExpressionList<T> idIn(Object... idValues) { return add(expr.idIn(idValues)); } @Override public ExpressionList<T> idIn(Collection<?> idCollection) { return add(expr.idIn(idCollection)); } @Override public ExpressionList<T> idEq(Object value) { if (query != null && parentExprList == null) { query.setId(value); } else { add(expr.idEq(value)); } return this; } @Override public ExpressionList<T> iendsWith(String propertyName, String value) { return add(expr.iendsWith(propertyName, value)); } @Override public ExpressionList<T> ilike(String propertyName, String value) { return add(expr.ilike(propertyName, value)); } @Override public ExpressionList<T> inPairs(Pairs pairs) { return add(expr.inPairs(pairs)); } @Override public ExpressionList<T> in(String propertyName, Query<?> subQuery) { return add(expr.in(propertyName, subQuery)); } @Override public ExpressionList<T> in(String propertyName, Collection<?> values) { return add(expr.in(propertyName, values)); } @Override public ExpressionList<T> inOrEmpty(String propertyName, Collection<?> values) { if (notEmpty(values)) { add(expr.in(propertyName, values)); } return this; } @Override public ExpressionList<T> in(String propertyName, Object... values) { return add(expr.in(propertyName, values)); } @Override public ExpressionList<T> notIn(String propertyName, Object... values) { return add(expr.notIn(propertyName, values)); } @Override public ExpressionList<T> notIn(String propertyName, Collection<?> values) { return add(expr.notIn(propertyName, values)); } @Override public ExpressionList<T> notIn(String propertyName, Query<?> subQuery) { return add(expr.notIn(propertyName, subQuery)); } @Override public ExpressionList<T> isEmpty(String propertyName) { return add(expr.isEmpty(propertyName)); } @Override public ExpressionList<T> isNotEmpty(String propertyName) { return add(expr.isNotEmpty(propertyName)); } @Override public ExpressionList<T> exists(Query<?> subQuery) { return add(expr.exists(subQuery)); } @Override public ExpressionList<T> notExists(Query<?> subQuery) { return add(expr.notExists(subQuery)); } @Override public ExpressionList<T> isNotNull(String propertyName) { return add(expr.isNotNull(propertyName)); } @Override public ExpressionList<T> isNull(String propertyName) { return add(expr.isNull(propertyName)); } @Override public ExpressionList<T> istartsWith(String propertyName, String value) { return add(expr.istartsWith(propertyName, value)); } @Override public ExpressionList<T> le(String propertyName, Object value) { return add(expr.le(propertyName, value)); } @Override public ExpressionList<T> exampleLike(Object example) { return add(expr.exampleLike(example)); } @Override public ExpressionList<T> iexampleLike(Object example) { return add(expr.iexampleLike(example)); } @Override public ExpressionList<T> like(String propertyName, String value) { return add(expr.like(propertyName, value)); } @Override public ExpressionList<T> lt(String propertyName, Object value) { return add(expr.lt(propertyName, value)); } @Override public ExpressionList<T> ltOrNull(String propertyName, Object value) { return add(expr.ltOrNull(propertyName, value)); } @Override public ExpressionList<T> leOrNull(String propertyName, Object value) { return add(expr.leOrNull(propertyName, value)); } @Override public ExpressionList<T> not(Expression exp) { return add(expr.not(exp)); } @Override public ExpressionList<T> or(Expression expOne, Expression expTwo) { return add(expr.or(expOne, expTwo)); } @Override public ExpressionList<T> arrayContains(String propertyName, Object... elementValue) { return add(expr.arrayContains(propertyName, elementValue)); } @Override public ExpressionList<T> arrayNotContains(String propertyName, Object... values) { return add(expr.arrayNotContains(propertyName, values)); } @Override public ExpressionList<T> arrayIsEmpty(String propertyName) { return add(expr.arrayIsEmpty(propertyName)); } @Override public ExpressionList<T> arrayIsNotEmpty(String propertyName) { return add(expr.arrayIsNotEmpty(propertyName)); } @Override public ExpressionList<T> raw(String raw, Object value) { return add(expr.raw(raw, value)); } @Override public ExpressionList<T> raw(String raw, Object... values) { return add(expr.raw(raw, values)); } @Override public ExpressionList<T> raw(String raw) { return add(expr.raw(raw)); } @Override public ExpressionList<T> rawOrEmpty(String raw, Collection<?> values) { if (notEmpty(values)) { add(expr.raw(raw, values)); } return this; } private boolean notEmpty(Collection<?> values) { return values != null && !values.isEmpty(); } @Override public ExpressionList<T> startsWith(String propertyName, String value) { return add(expr.startsWith(propertyName, value)); } @Override public ExpressionList<T> match(String propertyName, String search) { return match(propertyName, search, null); } @Override public ExpressionList<T> match(String propertyName, String search, Match options) { setUseDocStore(true); return add(expr.textMatch(propertyName, search, options)); } @Override public ExpressionList<T> multiMatch(String query, String... fields) { return multiMatch(query, MultiMatch.fields(fields)); } @Override public ExpressionList<T> multiMatch(String query, MultiMatch options) { setUseDocStore(true); return add(expr.textMultiMatch(query, options)); } @Override public ExpressionList<T> textSimple(String search, TextSimple options) { setUseDocStore(true); return add(expr.textSimple(search, options)); } @Override public ExpressionList<T> textQueryString(String search, TextQueryString options) { setUseDocStore(true); return add(expr.textQueryString(search, options)); } @Override public ExpressionList<T> textCommonTerms(String search, TextCommonTerms options) { setUseDocStore(true); return add(expr.textCommonTerms(search, options)); } protected Junction<T> junction(Junction.Type type) { Junction<T> junction = expr.junction(type, query, this); add(junction); return junction; } @Override public ExpressionList<T> endJunction() { return parentExprList == null ? this : parentExprList; } @Override public ExpressionList<T> endAnd() { return endJunction(); } @Override public ExpressionList<T> endOr() { return endJunction(); } @Override public ExpressionList<T> endNot() { return endJunction(); } @Override public Junction<T> and() { return conjunction(); } @Override public Junction<T> or() { return disjunction(); } @Override public Junction<T> not() { return junction(Junction.Type.NOT); } @Override public Junction<T> conjunction() { return junction(Junction.Type.AND); } @Override public Junction<T> disjunction() { return junction(Junction.Type.OR); } @Override public Junction<T> must() { setUseDocStore(true); return junction(Junction.Type.MUST); } @Override public Junction<T> should() { setUseDocStore(true); return junction(Junction.Type.SHOULD); } @Override public Junction<T> mustNot() { setUseDocStore(true); return junction(Junction.Type.MUST_NOT); } @Override public String nestedPath(BeanDescriptor<?> desc) { // effectively handled by JunctionExpression return null; }
Set the nested path that all contained expressions share.
/** * Set the nested path that all contained expressions share. */
public void setAllDocNested(String allDocNestedPath) { this.allDocNestedPath = allDocNestedPath; }
Replace the underlying expression list with one organised by nested path.
/** * Replace the underlying expression list with one organised by nested path. */
public void setUnderlying(List<SpiExpression> groupedByNesting) { this.list = groupedByNesting; }
Prepare expressions for document store nested path handling.
/** * Prepare expressions for document store nested path handling. */
public void prepareDocNested(BeanDescriptor<T> beanDescriptor) { PrepareDocNested.prepare(this, beanDescriptor); } public Object idEqualTo(String idName) { if (idName == null) { return null; } if (list.size() == 1) { return list.get(0).getIdEqualTo(idName); } return null; } }