001package io.ebean;
002
003import io.ebean.search.Match;
004import io.ebean.search.MultiMatch;
005import io.ebean.search.TextCommonTerms;
006import io.ebean.search.TextQueryString;
007import io.ebean.search.TextSimple;
008
009import javax.annotation.Nonnull;
010import javax.annotation.Nullable;
011import javax.persistence.NonUniqueResultException;
012import java.sql.Connection;
013import java.sql.Timestamp;
014import java.util.Collection;
015import java.util.List;
016import java.util.Map;
017import java.util.Optional;
018import java.util.Set;
019import java.util.function.Consumer;
020import java.util.function.Predicate;
021
022/**
023 * List of Expressions that make up a where or having clause.
024 * <p>
025 * An ExpressionList is returned from {@link Query#where()}.
026 * </p>
027 * <p>
028 * The ExpressionList has a list of convenience methods that create the standard
029 * expressions and add them to this list.
030 * </p>
031 * <p>
032 * The ExpressionList also duplicates methods that are found on the Query such
033 * as findList() and order(). The purpose of these methods is provide a fluid
034 * API. The upside of this approach is that you can build and execute a query
035 * via chained methods. The down side is that this ExpressionList object has
036 * more methods than you would initially expect (the ones duplicated from
037 * Query).
038 * </p>
039 *
040 * @see Query#where()
041 */
042public interface ExpressionList<T> {
043
044  /**
045   * Return the query that owns this expression list.
046   * <p>
047   * This is a convenience method solely to support a fluid API where the
048   * methods are chained together. Adding expressions returns this expression
049   * list and this method can be used after that to return back the original
050   * query so that further things can be added to it.
051   * </p>
052   */
053  Query<T> query();
054
055  /**
056   * Controls, if paginated queries should always append an 'order by id' statement at the end to
057   * guarantee a deterministic sort result. This may affect performance.
058   * If this is not enabled, and an orderBy is set on the query, it's up to the programmer that
059   * this query provides a deterministic result.
060   */
061  Query<T> orderById(boolean orderById);
062
063  /**
064   * Set the order by clause replacing the existing order by clause if there is
065   * one.
066   * <p>
067   * This follows SQL syntax using commas between each property with the
068   * optional asc and desc keywords representing ascending and descending order
069   * respectively.
070   */
071  ExpressionList<T> order(String orderByClause);
072
073  /**
074   * Set the order by clause replacing the existing order by clause if there is
075   * one.
076   * <p>
077   * This follows SQL syntax using commas between each property with the
078   * optional asc and desc keywords representing ascending and descending order
079   * respectively.
080   */
081  ExpressionList<T> orderBy(String orderBy);
082
083  /**
084   * Return the OrderBy so that you can append an ascending or descending
085   * property to the order by clause.
086   * <p>
087   * This will never return a null. If no order by clause exists then an 'empty'
088   * OrderBy object is returned.
089   * <p>
090   * This is the same as <code>orderBy()</code>
091   */
092  OrderBy<T> order();
093
094  /**
095   * Return the OrderBy so that you can append an ascending or descending
096   * property to the order by clause.
097   * <p>
098   * This will never return a null. If no order by clause exists then an 'empty'
099   * OrderBy object is returned.
100   * <p>
101   * This is the same as <code>order()</code>
102   */
103  OrderBy<T> orderBy();
104
105  /**
106   * Deprecated migrate to {@link #orderBy(String)}
107   */
108  @Deprecated
109  Query<T> setOrderBy(String orderBy);
110
111  /**
112   * Apply the path properties to the query replacing the select and fetch clauses.
113   */
114  Query<T> apply(FetchPath fetchPath);
115
116  /**
117   * Perform an 'As of' query using history tables to return the object graph
118   * as of a time in the past.
119   * <p>
120   * To perform this query the DB must have underlying history tables.
121   * </p>
122   *
123   * @param asOf the date time in the past at which you want to view the data
124   */
125  Query<T> asOf(Timestamp asOf);
126
127  /**
128   * Execute the query against the draft set of tables.
129   */
130  Query<T> asDraft();
131
132  /**
133   * Convert the query to a DTO bean query.
134   * <p>
135   * We effectively use the underlying ORM query to build the SQL and then execute
136   * and map it into DTO beans.
137   */
138  <D> DtoQuery<D> asDto(Class<D> dtoClass);
139
140  /**
141   * Return the underlying query as an UpdateQuery.
142   * <p>
143   * Typically this is used with query beans to covert a query bean
144   * query into an UpdateQuery like the examples below.
145   * </p>
146   *
147   * <pre>{@code
148   *
149   *  int rowsUpdated = new QCustomer()
150   *       .name.startsWith("Rob")
151   *       .asUpdate()
152   *       .set("active", false)
153   *       .update();;
154   *
155   * }</pre>
156   *
157   * <pre>{@code
158   *
159   *   int rowsUpdated = new QContact()
160   *       .notes.note.startsWith("Make Inactive")
161   *       .email.endsWith("@foo.com")
162   *       .customer.id.equalTo(42)
163   *       .asUpdate()
164   *       .set("inactive", true)
165   *       .setRaw("email = lower(email)")
166   *       .update();
167   *
168   * }</pre>
169   */
170  UpdateQuery<T> asUpdate();
171
172  /**
173   * Execute the query with the given lock type and WAIT.
174   * <p>
175   * Note that <code>forUpdate()</code> is the same as
176   * <code>withLock(LockType.UPDATE)</code>.
177   * <p>
178   * Provides us with the ability to explicitly use Postgres
179   * SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
180   */
181  Query<T> withLock(Query.LockType lockType);
182
183  /**
184   * Execute the query with the given lock type and lock wait.
185   * <p>
186   * Note that <code>forUpdateNoWait()</code> is the same as
187   * <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
188   * <p>
189   * Provides us with the ability to explicitly use Postgres
190   * SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
191   */
192  Query<T> withLock(Query.LockType lockType, Query.LockWait lockWait);
193
194  /**
195   * Execute using "for update" clause which results in the DB locking the record.
196   */
197  Query<T> forUpdate();
198
199  /**
200   * Deprecated - migrate to withLock().
201   * Execute using "for update" with given lock type (currently Postgres only).
202   */
203  @Deprecated
204  Query<T> forUpdate(Query.LockType lockType);
205
206  /**
207   * Execute using "for update" clause with No Wait option.
208   * <p>
209   * This is typically a Postgres and Oracle only option at this stage.
210   * </p>
211   */
212  Query<T> forUpdateNoWait();
213
214  /**
215   * Deprecated - migrate to withLock().
216   * Execute using "for update nowait" with given lock type (currently Postgres only).
217   */
218  @Deprecated
219  Query<T> forUpdateNoWait(Query.LockType lockType);
220
221  /**
222   * Execute using "for update" clause with Skip Locked option.
223   * <p>
224   * This is typically a Postgres and Oracle only option at this stage.
225   * </p>
226   */
227  Query<T> forUpdateSkipLocked();
228
229  /**
230   * Deprecated - migrate to withLock().
231   * Execute using "for update skip locked" with given lock type (currently Postgres only).
232   */
233  @Deprecated
234  Query<T> forUpdateSkipLocked(Query.LockType lockType);
235
236  /**
237   * Execute the query including soft deleted rows.
238   */
239  Query<T> setIncludeSoftDeletes();
240
241  /**
242   * Execute the query using the given transaction.
243   */
244  Query<T> usingTransaction(Transaction transaction);
245
246  /**
247   * Execute the query using the given connection.
248   */
249  Query<T> usingConnection(Connection connection);
250
251  /**
252   * Execute as a delete query deleting the 'root level' beans that match the predicates
253   * in the query.
254   * <p>
255   * Note that if the query includes joins then the generated delete statement may not be
256   * optimal depending on the database platform.
257   * </p>
258   *
259   * @return the number of rows that were deleted.
260   */
261  int delete();
262
263  /**
264   * Execute as a delete query deleting the 'root level' beans that match the predicates
265   * in the query.
266   * <p>
267   * Note that if the query includes joins then the generated delete statement may not be
268   * optimal depending on the database platform.
269   * </p>
270   *
271   * @return the number of rows that were deleted.
272   */
273  int delete(Transaction transaction);
274
275  /**
276   * Execute as a update query.
277   *
278   * @return the number of rows that were updated.
279   * @see UpdateQuery
280   */
281  int update();
282
283  /**
284   * Execute as a update query with the given transaction.
285   *
286   * @return the number of rows that were updated.
287   * @see UpdateQuery
288   */
289  int update(Transaction transaction);
290
291  /**
292   * Execute the query returning true if a row is found.
293   * <p>
294   * The query is executed using max rows of 1 and will only select the id property.
295   * This method is really just a convenient way to optimise a query to perform a
296   * 'does a row exist in the db' check.
297   * </p>
298   *
299   * <h2>Example:</h2>
300   * <pre>{@code
301   *
302   *   boolean userExists = query().where().eq("email", "rob@foo.com").exists();
303   *
304   * }</pre>
305   *
306   * <h2>Example using a query bean:</h2>
307   * <pre>{@code
308   *
309   *   boolean userExists = new QContact().email.equalTo("rob@foo.com").exists();
310   *
311   * }</pre>
312   *
313   * @return True if the query finds a matching row in the database
314   */
315  boolean exists();
316
317  /**
318   * Execute the query iterating over the results.
319   *
320   * @see Query#findIterate()
321   */
322  QueryIterator<T> findIterate();
323
324  /**
325   * Execute the query process the beans one at a time.
326   *
327   * @see Query#findEach(Consumer)
328   */
329  void findEach(Consumer<T> consumer);
330
331  /**
332   * Execute the query processing the beans one at a time with the ability to
333   * stop processing before reading all the beans.
334   *
335   * @see Query#findEachWhile(Predicate)
336   */
337  void findEachWhile(Predicate<T> consumer);
338
339  /**
340   * Execute the query returning a list.
341   *
342   * @see Query#findList()
343   */
344  @Nonnull
345  List<T> findList();
346
347  /**
348   * Execute the query returning the list of Id's.
349   *
350   * @see Query#findIds()
351   */
352  @Nonnull
353  <A> List<A> findIds();
354
355  /**
356   * Return the count of entities this query should return.
357   * <p>
358   * This is the number of 'top level' or 'root level' entities.
359   * </p>
360   */
361  int findCount();
362
363  /**
364   * Execute the query returning a set.
365   *
366   * @see Query#findSet()
367   */
368  @Nonnull
369  Set<T> findSet();
370
371  /**
372   * Execute the query returning a map.
373   *
374   * @see Query#findMap()
375   */
376  @Nonnull
377  <K> Map<K, T> findMap();
378
379  /**
380   * Execute the query returning a list of values for a single property.
381   *
382   * <h3>Example 1:</h3>
383   * <pre>{@code
384   *
385   *  List<String> names =
386   *    DB.find(Customer.class)
387   *      .select("name")
388   *      .order().asc("name")
389   *      .findSingleAttributeList();
390   *
391   * }</pre>
392   *
393   * <h3>Example 2:</h3>
394   * <pre>{@code
395   *
396   *  List<String> names =
397   *    DB.find(Customer.class)
398   *      .setDistinct(true)
399   *      .select("name")
400   *      .where().eq("status", Customer.Status.NEW)
401   *      .order().asc("name")
402   *      .setMaxRows(100)
403   *      .findSingleAttributeList();
404   *
405   * }</pre>
406   *
407   * @return the list of values for the selected property
408   */
409  @Nonnull
410  <A> List<A> findSingleAttributeList();
411
412  /**
413   * Execute a query returning a single value of a single property/column.
414   * <pre>{@code
415   *
416   *  String name =
417   *    DB.find(Customer.class)
418   *      .select("name")
419   *      .where().eq("id", 42)
420   *      .findSingleAttribute();
421   *
422   * }</pre>
423   */
424  default <A> A findSingleAttribute() {
425    List<A> list = findSingleAttributeList();
426    return !list.isEmpty() ? list.get(0) : null;
427  }
428
429  /**
430   * Execute the query returning a single bean or null (if no matching
431   * bean is found).
432   * <p>
433   * If more than 1 row is found for this query then a NonUniqueResultException is
434   * thrown.
435   * </p>
436   *
437   * @throws NonUniqueResultException if more than one result was found
438   * @see Query#findOne()
439   */
440  @Nullable
441  T findOne();
442
443  /**
444   * Execute the query returning an optional bean.
445   */
446  @Nonnull
447  Optional<T> findOneOrEmpty();
448
449  /**
450   * Execute find row count query in a background thread.
451   * <p>
452   * This returns a Future object which can be used to cancel, check the
453   * execution status (isDone etc) and get the value (with or without a
454   * timeout).
455   * </p>
456   *
457   * @return a Future object for the row count query
458   */
459  @Nonnull
460  FutureRowCount<T> findFutureCount();
461
462  /**
463   * Execute find Id's query in a background thread.
464   * <p>
465   * This returns a Future object which can be used to cancel, check the
466   * execution status (isDone etc) and get the value (with or without a
467   * timeout).
468   * </p>
469   *
470   * @return a Future object for the list of Id's
471   */
472  @Nonnull
473  FutureIds<T> findFutureIds();
474
475  /**
476   * Execute find list query in a background thread.
477   * <p>
478   * This returns a Future object which can be used to cancel, check the
479   * execution status (isDone etc) and get the value (with or without a
480   * timeout).
481   * </p>
482   *
483   * @return a Future object for the list result of the query
484   */
485  @Nonnull
486  FutureList<T> findFutureList();
487
488  /**
489   * Return a PagedList for this query using firstRow and maxRows.
490   * <p>
491   * The benefit of using this over findList() is that it provides functionality to get the
492   * total row count etc.
493   * </p>
494   * <p>
495   * If maxRows is not set on the query prior to calling findPagedList() then a
496   * PersistenceException is thrown.
497   * </p>
498   * <pre>{@code
499   *
500   *  PagedList<Order> pagedList = DB.find(Order.class)
501   *       .setFirstRow(50)
502   *       .setMaxRows(20)
503   *       .findPagedList();
504   *
505   *       // fetch the total row count in the background
506   *       pagedList.loadRowCount();
507   *
508   *       List<Order> orders = pagedList.getList();
509   *       int totalRowCount = pagedList.getTotalRowCount();
510   *
511   * }</pre>
512   *
513   * @return The PagedList
514   * @see Query#findPagedList()
515   */
516  @Nonnull
517  PagedList<T> findPagedList();
518
519  /**
520   * Return versions of a @History entity bean.
521   * <p>
522   * Generally this query is expected to be a find by id or unique predicates query.
523   * It will execute the query against the history returning the versions of the bean.
524   * </p>
525   */
526  @Nonnull
527  List<Version<T>> findVersions();
528
529  /**
530   * Return versions of a @History entity bean between the 2 timestamps.
531   * <p>
532   * Generally this query is expected to be a find by id or unique predicates query.
533   * It will execute the query against the history returning the versions of the bean.
534   * </p>
535   */
536  @Nonnull
537  List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
538
539  /**
540   * Add some filter predicate expressions to the many property.
541   */
542  @Nonnull
543  ExpressionList<T> filterMany(String manyProperty);
544
545  /**
546   * Add filter expressions to the many property.
547   *
548   * <pre>{@code
549   *
550   *   DB.find(Customer.class)
551   *   .where()
552   *   .eq("name", "Rob")
553   *   .filterMany("orders", "status = ?", Status.NEW)
554   *   .findList();
555   *
556   * }</pre>
557   *
558   * @param manyProperty The many property
559   * @param expressions  Filter expressions with and, or and ? or ?1 type bind parameters
560   * @param params       Bind parameters used in the expressions
561   */
562  ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params);
563
564  /**
565   * Specify specific properties to fetch on the main/root bean (aka partial
566   * object).
567   *
568   * @see Query#select(String)
569   */
570  Query<T> select(String properties);
571
572  /**
573   * Apply the fetchGroup which defines what part of the object graph to load.
574   */
575  Query<T> select(FetchGroup<T> fetchGroup);
576
577  /**
578   * Set whether this query uses DISTINCT.
579   * <p>
580   * The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that
581   * generally ORM queries include the "id" property and this doesn't make sense for distinct queries.
582   * </p>
583   * <pre>{@code
584   *
585   *   List<Customer> customers =
586   *       DB.find(Customer.class)
587   *          .setDistinct(true)
588   *          .select("name")     // only select the customer name
589   *          .findList();
590   *
591   * }</pre>
592   */
593  Query<T> setDistinct(boolean distinct);
594
595  /**
596   * Set the index(es) to search for a document store which uses partitions.
597   * <p>
598   * For example, when executing a query against ElasticSearch with daily indexes we can
599   * explicitly specify the indexes to search against.
600   * </p>
601   *
602   * @param indexName The index or indexes to search against
603   * @return This query
604   * @see Query#setDocIndexName(String)
605   */
606  Query<T> setDocIndexName(String indexName);
607
608  /**
609   * Set the first row to fetch.
610   *
611   * @see Query#setFirstRow(int)
612   */
613  ExpressionList<T> setFirstRow(int firstRow);
614
615  /**
616   * Set the maximum number of rows to fetch.
617   *
618   * @see Query#setMaxRows(int)
619   */
620  ExpressionList<T> setMaxRows(int maxRows);
621
622  /**
623   * Set the name of the property which values become the key of a map.
624   *
625   * @see Query#setMapKey(String)
626   */
627  Query<T> setMapKey(String mapKey);
628
629  /**
630   * Set to true when this query should use the bean cache.
631   * <p>
632   * This is now the same as setUseBeanCache(CacheMode.ON) and will be deprecated.
633   * </p>
634   *
635   * @see Query#setUseCache(boolean)
636   */
637  Query<T> setUseCache(boolean useCache);
638
639  /**
640   * Set the mode to use the bean cache when executing this query.
641   *
642   * @see Query#setBeanCacheMode(CacheMode)
643   */
644  Query<T> setBeanCacheMode(CacheMode beanCacheMode);
645
646  /**
647   * Set the {@link CacheMode} to use the query cache for executing this query.
648   *
649   * @see Query#setUseQueryCache(boolean)
650   */
651  Query<T> setUseQueryCache(CacheMode useCache);
652
653  /**
654   * Extended version for setDistinct in conjunction with "findSingleAttributeList";
655   * <pre>{@code
656   *
657   *  List<CountedValue<Order.Status>> orderStatusCount =
658   *
659   *     DB.find(Order.class)
660   *      .select("status")
661   *      .where()
662   *      .gt("orderDate", LocalDate.now().minusMonths(3))
663   *
664   *      // fetch as single attribute with a COUNT
665   *      .setCountDistinct(CountDistinctOrder.COUNT_DESC_ATTR_ASC)
666   *      .findSingleAttributeList();
667   *
668   *     for (CountedValue<Order.Status> entry : orderStatusCount) {
669   *       System.out.println(" count:" + entry.getCount()+" orderStatus:" + entry.getValue() );
670   *     }
671   *
672   *   // produces
673   *
674   *   count:3 orderStatus:NEW
675   *   count:1 orderStatus:SHIPPED
676   *   count:1 orderStatus:COMPLETE
677   *
678   * }</pre>
679   */
680  Query<T> setCountDistinct(CountDistinctOrder orderBy);
681
682  /**
683   * Calls {@link #setUseQueryCache(CacheMode)} with <code>ON</code> or <code>OFF</code>.
684   *
685   * @see Query#setUseQueryCache(CacheMode)
686   */
687  default Query<T> setUseQueryCache(boolean enabled) {
688    return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF);
689  }
690
691  /**
692   * Set to true if this query should execute against the doc store.
693   * <p>
694   * When setting this you may also consider disabling lazy loading.
695   * </p>
696   */
697  Query<T> setUseDocStore(boolean useDocsStore);
698
699  /**
700   * Set true if you want to disable lazy loading.
701   * <p>
702   * That is, once the object graph is returned further lazy loading is disabled.
703   * </p>
704   */
705  Query<T> setDisableLazyLoading(boolean disableLazyLoading);
706
707  /**
708   * Disable read auditing for this query.
709   * <p>
710   * This is intended to be used when the query is not a user initiated query and instead
711   * part of the internal processing in an application to load a cache or document store etc.
712   * In these cases we don't want the query to be part of read auditing.
713   * </p>
714   */
715  Query<T> setDisableReadAuditing();
716
717  /**
718   * Set a label on the query (to help identify query execution statistics).
719   */
720  Query<T> setLabel(String label);
721
722  /**
723   * Add expressions to the having clause.
724   * <p>
725   * The having clause is only used for queries based on raw sql (via SqlSelect
726   * annotation etc).
727   * </p>
728   */
729  ExpressionList<T> having();
730
731  /**
732   * Add another expression to the where clause.
733   */
734  ExpressionList<T> where();
735
736  /**
737   * Add the expressions to this expression list.
738   *
739   * @param expressions The expressions that are parsed and added to this expression list
740   * @param params      Bind parameters to match ? or ?1 bind positions.
741   */
742  ExpressionList<T> where(String expressions, Object... params);
743
744  /**
745   * Path exists - for the given path in a JSON document.
746   * <pre>{@code
747   *
748   *   where().jsonExists("content", "path.other")
749   *
750   * }</pre>
751   *
752   * @param propertyName the property that holds a JSON document
753   * @param path         the nested path in the JSON document in dot notation
754   */
755  ExpressionList<T> jsonExists(String propertyName, String path);
756
757  /**
758   * Path does not exist - for the given path in a JSON document.
759   * <pre>{@code
760   *
761   *   where().jsonNotExists("content", "path.other")
762   *
763   * }</pre>
764   *
765   * @param propertyName the property that holds a JSON document
766   * @param path         the nested path in the JSON document in dot notation
767   */
768  ExpressionList<T> jsonNotExists(String propertyName, String path);
769
770  /**
771   * Equal to expression for the value at the given path in the JSON document.
772   * <pre>{@code
773   *
774   *   where().jsonEqualTo("content", "path.other", 34)
775   *
776   * }</pre>
777   *
778   * @param propertyName the property that holds a JSON document
779   * @param path         the nested path in the JSON document in dot notation
780   * @param value        the value used to test against the document path's value
781   */
782  ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value);
783
784  /**
785   * Not Equal to - for the given path in a JSON document.
786   * <pre>{@code
787   *
788   *   where().jsonNotEqualTo("content", "path.other", 34)
789   *
790   * }</pre>
791   *
792   * @param propertyName the property that holds a JSON document
793   * @param path         the nested path in the JSON document in dot notation
794   * @param value        the value used to test against the document path's value
795   */
796  ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object value);
797
798  /**
799   * Greater than - for the given path in a JSON document.
800   * <pre>{@code
801   *
802   *   where().jsonGreaterThan("content", "path.other", 34)
803   *
804   * }</pre>
805   */
806  ExpressionList<T> jsonGreaterThan(String propertyName, String path, Object value);
807
808  /**
809   * Greater than or equal to - for the given path in a JSON document.
810   * <pre>{@code
811   *
812   *   where().jsonGreaterOrEqual("content", "path.other", 34)
813   *
814   * }</pre>
815   */
816  ExpressionList<T> jsonGreaterOrEqual(String propertyName, String path, Object value);
817
818  /**
819   * Less than - for the given path in a JSON document.
820   * <pre>{@code
821   *
822   *   where().jsonLessThan("content", "path.other", 34)
823   *
824   * }</pre>
825   */
826  ExpressionList<T> jsonLessThan(String propertyName, String path, Object value);
827
828  /**
829   * Less than or equal to - for the given path in a JSON document.
830   * <pre>{@code
831   *
832   *   where().jsonLessOrEqualTo("content", "path.other", 34)
833   *
834   * }</pre>
835   */
836  ExpressionList<T> jsonLessOrEqualTo(String propertyName, String path, Object value);
837
838  /**
839   * Between - for the given path in a JSON document.
840   * <pre>{@code
841   *
842   *   where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime)
843   *
844   * }</pre>
845   */
846  ExpressionList<T> jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue);
847
848  /**
849   * Add an Expression to the list.
850   */
851  ExpressionList<T> add(Expression expr);
852
853  /**
854   * Add a list of Expressions to this ExpressionList.s
855   */
856  ExpressionList<T> addAll(ExpressionList<T> exprList);
857
858  /**
859   * Equal To - property is equal to a given value.
860   */
861  ExpressionList<T> eq(String propertyName, Object value);
862
863  /**
864   * Equal To or Null - property is equal to a given value or null.
865   */
866  ExpressionList<T> eqOrNull(String propertyName, Object value);
867
868  /**
869   * Not Equal To - property not equal to the given value.
870   */
871  ExpressionList<T> ne(String propertyName, Object value);
872
873  /**
874   * Case Insensitive Equal To - property equal to the given value (typically
875   * using a lower() function to make it case insensitive).
876   */
877  ExpressionList<T> ieq(String propertyName, String value);
878
879  /**
880   * Case Insensitive Not Equal To - property not equal to the given value (typically
881   * using a lower() function to make it case insensitive).
882   */
883  ExpressionList<T> ine(String propertyName, String value);
884
885  /**
886   * Value in Range between 2 properties.
887   *
888   * <pre>{@code
889   *
890   *    .startDate.inRangeWith(endDate, now)
891   *
892   *    // which equates to
893   *    startDate <= now and (endDate > now or endDate is null)
894   *
895   * }</pre>
896   *
897   * <p>
898   * This is a convenience expression combining a number of simple expressions.
899   * The most common use of this could be called "effective dating" where 2 date or
900   * timestamp columns represent the date range in which
901   */
902  ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value);
903
904  /**
905   * In Range - {@code property >= value1 and property < value2}.
906   * <p>
907   * Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
908   * </p>
909   */
910  ExpressionList<T> inRange(String propertyName, Object value1, Object value2);
911
912  /**
913   * Between - property between the two given values.
914   */
915  ExpressionList<T> between(String propertyName, Object value1, Object value2);
916
917  /**
918   * Between - value between the two properties.
919   */
920  ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value);
921
922  /**
923   * Greater Than - property greater than the given value.
924   */
925  ExpressionList<T> gt(String propertyName, Object value);
926
927  /**
928   * Greater Than or Null - property greater than the given value or null.
929   */
930  ExpressionList<T> gtOrNull(String propertyName, Object value);
931
932  /**
933   * Greater Than or Equal to OR Null - <code> >= or null </code>.
934   */
935  ExpressionList<T> geOrNull(String propertyName, Object value);
936
937  /**
938   * Greater Than or Equal to - property greater than or equal to the given
939   * value.
940   */
941  ExpressionList<T> ge(String propertyName, Object value);
942
943  /**
944   * Less Than - property less than the given value.
945   */
946  ExpressionList<T> lt(String propertyName, Object value);
947
948  /**
949   * Less Than or Null - property less than the given value or null.
950   */
951  ExpressionList<T> ltOrNull(String propertyName, Object value);
952
953  /**
954   * Less Than or Equal to OR Null - <code> <= or null </code>.
955   */
956  ExpressionList<T> leOrNull(String propertyName, Object value);
957
958  /**
959   * Less Than or Equal to - property less than or equal to the given value.
960   */
961  ExpressionList<T> le(String propertyName, Object value);
962
963  /**
964   * Is Null - property is null.
965   */
966  ExpressionList<T> isNull(String propertyName);
967
968  /**
969   * Is Not Null - property is not null.
970   */
971  ExpressionList<T> isNotNull(String propertyName);
972
973  /**
974   * A "Query By Example" type of expression.
975   * <p>
976   * Pass in an example entity and for each non-null scalar properties an
977   * expression is added.
978   * </p>
979   * <p>
980   * By Default this case sensitive, will ignore numeric zero values and will
981   * use a Like for string values (you must put in your own wildcards).
982   * </p>
983   * <p>
984   * To get control over the options you can create an ExampleExpression and set
985   * those options such as case insensitive etc.
986   * </p>
987   * <pre>{@code
988   *
989   * // create an example bean and set the properties
990   * // with the query parameters you want
991   * Customer example = new Customer();
992   * example.setName("Rob%");
993   * example.setNotes("%something%");
994   *
995   * List<Customer> list =
996   *   DB.find(Customer.class)
997   *     .where().exampleLike(example)
998   *     .findList();
999   *
1000   * }</pre>
1001   * <p>
1002   * Similarly you can create an ExampleExpression
1003   * </p>
1004   * <pre>{@code
1005   *
1006   * Customer example = new Customer();
1007   * example.setName("Rob%");
1008   * example.setNotes("%something%");
1009   *
1010   * // create a ExampleExpression with more control
1011   * ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO).includeZeros();
1012   *
1013   * List<Customer> list = DB.find(Customer.class).where().add(qbe).findList();
1014   *
1015   * }</pre>
1016   */
1017  ExpressionList<T> exampleLike(Object example);
1018
1019  /**
1020   * Case insensitive version of {@link #exampleLike(Object)}
1021   */
1022  ExpressionList<T> iexampleLike(Object example);
1023
1024  /**
1025   * Like - property like value where the value contains the SQL wild card
1026   * characters % (percentage) and _ (underscore).
1027   */
1028  ExpressionList<T> like(String propertyName, String value);
1029
1030  /**
1031   * Case insensitive Like - property like value where the value contains the
1032   * SQL wild card characters % (percentage) and _ (underscore). Typically uses
1033   * a lower() function to make the expression case insensitive.
1034   */
1035  ExpressionList<T> ilike(String propertyName, String value);
1036
1037  /**
1038   * Starts With - property like value%.
1039   */
1040  ExpressionList<T> startsWith(String propertyName, String value);
1041
1042  /**
1043   * Case insensitive Starts With - property like value%. Typically uses a
1044   * lower() function to make the expression case insensitive.
1045   */
1046  ExpressionList<T> istartsWith(String propertyName, String value);
1047
1048  /**
1049   * Ends With - property like %value.
1050   */
1051  ExpressionList<T> endsWith(String propertyName, String value);
1052
1053  /**
1054   * Case insensitive Ends With - property like %value. Typically uses a lower()
1055   * function to make the expression case insensitive.
1056   */
1057  ExpressionList<T> iendsWith(String propertyName, String value);
1058
1059  /**
1060   * Contains - property like %value%.
1061   */
1062  ExpressionList<T> contains(String propertyName, String value);
1063
1064  /**
1065   * Case insensitive Contains - property like %value%. Typically uses a lower()
1066   * function to make the expression case insensitive.
1067   */
1068  ExpressionList<T> icontains(String propertyName, String value);
1069
1070  /**
1071   * In expression using pairs of value objects.
1072   */
1073  ExpressionList<T> inPairs(Pairs pairs);
1074
1075  /**
1076   * In - using a subQuery.
1077   */
1078  ExpressionList<T> in(String propertyName, Query<?> subQuery);
1079
1080  /**
1081   * In - property has a value in the array of values.
1082   */
1083  ExpressionList<T> in(String propertyName, Object... values);
1084
1085  /**
1086   * In - property has a value in the collection of values.
1087   */
1088  ExpressionList<T> in(String propertyName, Collection<?> values);
1089
1090  /**
1091   * In where null or empty values means that no predicate is added to the query.
1092   * <p>
1093   * That is, only add the IN predicate if the values are not null or empty.
1094   * <p>
1095   * Without this we typically need to code an <code>if</code> block to only add
1096   * the IN predicate if the collection is not empty like:
1097   * </p>
1098   *
1099   * <h3>Without inOrEmpty()</h3>
1100   * <pre>{@code
1101   *
1102   *   query.where() // add some predicates
1103   *     .eq("status", Status.NEW);
1104   *
1105   *   if (ids != null && !ids.isEmpty()) {
1106   *     query.where().in("customer.id", ids);
1107   *   }
1108   *
1109   *   query.findList();
1110   *
1111   * }</pre>
1112   *
1113   * <h3>Using inOrEmpty()</h3>
1114   * <pre>{@code
1115   *
1116   *   query.where()
1117   *     .eq("status", Status.NEW)
1118   *     .inOrEmpty("customer.id", ids)
1119   *     .findList();
1120   *
1121   * }</pre>
1122   */
1123  ExpressionList<T> inOrEmpty(String propertyName, Collection<?> values);
1124
1125  /**
1126   * In - using a subQuery.
1127   * <p>
1128   * This is exactly the same as in() and provided due to "in" being a Kotlin keyword
1129   * (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
1130   */
1131  default ExpressionList<T> isIn(String propertyName, Query<?> subQuery) {
1132    return in(propertyName, subQuery);
1133  }
1134
1135  /**
1136   * In - property has a value in the array of values.
1137   * <p>
1138   * This is exactly the same as in() and provided due to "in" being a Kotlin keyword
1139   * (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
1140   */
1141  default ExpressionList<T> isIn(String propertyName, Object... values) {
1142    return in(propertyName, values);
1143  }
1144
1145  /**
1146   * In - property has a value in the collection of values.
1147   * <p>
1148   * This is exactly the same as in() and provided due to "in" being a Kotlin keyword
1149   * (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
1150   */
1151  default ExpressionList<T> isIn(String propertyName, Collection<?> values) {
1152    return in(propertyName, values);
1153  }
1154
1155  /**
1156   * Not In - property has a value in the array of values.
1157   */
1158  ExpressionList<T> notIn(String propertyName, Object... values);
1159
1160  /**
1161   * Not In - property has a value in the collection of values.
1162   */
1163  ExpressionList<T> notIn(String propertyName, Collection<?> values);
1164
1165  /**
1166   * Not In - using a subQuery.
1167   */
1168  ExpressionList<T> notIn(String propertyName, Query<?> subQuery);
1169
1170  /**
1171   * Is empty expression for collection properties.
1172   */
1173  ExpressionList<T> isEmpty(String propertyName);
1174
1175  /**
1176   * Is not empty expression for collection properties.
1177   */
1178  ExpressionList<T> isNotEmpty(String propertyName);
1179
1180  /**
1181   * Exists expression
1182   */
1183  ExpressionList<T> exists(Query<?> subQuery);
1184
1185  /**
1186   * Not exists expression
1187   */
1188  ExpressionList<T> notExists(Query<?> subQuery);
1189
1190  /**
1191   * Id IN a list of id values.
1192   */
1193  ExpressionList<T> idIn(Object... idValues);
1194
1195  /**
1196   * Id IN a collection of id values.
1197   */
1198  ExpressionList<T> idIn(Collection<?> idValues);
1199
1200  /**
1201   * Id Equal to - ID property is equal to the value.
1202   */
1203  ExpressionList<T> idEq(Object value);
1204
1205  /**
1206   * All Equal - Map containing property names and their values.
1207   * <p>
1208   * Expression where all the property names in the map are equal to the
1209   * corresponding value.
1210   * </p>
1211   *
1212   * @param propertyMap a map keyed by property names.
1213   */
1214  ExpressionList<T> allEq(Map<String, Object> propertyMap);
1215
1216  /**
1217   * Array property contains entries with the given values.
1218   */
1219  ExpressionList<T> arrayContains(String propertyName, Object... values);
1220
1221  /**
1222   * Array does not contain the given values.
1223   * <p>
1224   * Array support is effectively limited to Postgres at this time.
1225   * </p>
1226   */
1227  ExpressionList<T> arrayNotContains(String propertyName, Object... values);
1228
1229  /**
1230   * Array is empty - for the given array property.
1231   * <p>
1232   * Array support is effectively limited to Postgres at this time.
1233   * </p>
1234   */
1235  ExpressionList<T> arrayIsEmpty(String propertyName);
1236
1237  /**
1238   * Array is not empty - for the given array property.
1239   * <p>
1240   * Array support is effectively limited to Postgres at this time.
1241   * </p>
1242   */
1243  ExpressionList<T> arrayIsNotEmpty(String propertyName);
1244
1245  /**
1246   * Add expression for ANY of the given bit flags to be set.
1247   * <pre>{@code
1248   *
1249   * where().bitwiseAny("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
1250   *
1251   * }</pre>
1252   *
1253   * @param propertyName The property that holds the flags value
1254   * @param flags        The flags we are looking for
1255   */
1256  ExpressionList<T> bitwiseAny(String propertyName, long flags);
1257
1258  /**
1259   * Add expression for ALL of the given bit flags to be set.
1260   * <pre>{@code
1261   *
1262   * where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
1263   *
1264   * }</pre>
1265   *
1266   * @param propertyName The property that holds the flags value
1267   * @param flags        The flags we are looking for
1268   */
1269  ExpressionList<T> bitwiseAll(String propertyName, long flags);
1270
1271  /**
1272   * Add expression for the given bit flags to be NOT set.
1273   * <pre>{@code
1274   *
1275   * where().bitwiseNot("flags", BwFlags.HAS_COLOUR)
1276   *
1277   * }</pre>
1278   *
1279   * @param propertyName The property that holds the flags value
1280   * @param flags        The flags we are looking for
1281   */
1282  ExpressionList<T> bitwiseNot(String propertyName, long flags);
1283
1284  /**
1285   * Add bitwise AND expression of the given bit flags to compare with the match/mask.
1286   * <p>
1287   * <pre>{@code
1288   *
1289   * // Flags Bulk + Size = Size
1290   * // ... meaning Bulk is not set and Size is set
1291   *
1292   * long selectedFlags = BwFlags.HAS_BULK + BwFlags.HAS_SIZE;
1293   * long mask = BwFlags.HAS_SIZE; // Only Size flag set
1294   *
1295   * where().bitwiseAnd("flags", selectedFlags, mask)
1296   *
1297   * }</pre>
1298   *
1299   * @param propertyName The property that holds the flags value
1300   * @param flags        The flags we are looking for
1301   */
1302  ExpressionList<T> bitwiseAnd(String propertyName, long flags, long match);
1303
1304  /**
1305   * Add raw expression with a single parameter.
1306   * <p>
1307   * The raw expression should contain a single ? or ?1
1308   * at the location of the parameter.  We use ?1 when binding a
1309   * collection for an IN expression.
1310   * <p>
1311   * When properties in the clause are fully qualified as table-column names
1312   * then they are not translated. logical property name names (not fully
1313   * qualified) will still be translated to their physical name.
1314   * <p>
1315   * <h4>Examples:</h4>
1316   * <pre>{@code
1317   *
1318   *   // use a database function
1319   *   raw("add_days(orderDate, 10) < ?", someDate)
1320   *
1321   *   raw("name like ?", "Rob%")
1322   *
1323   *   raw("name in (?1)", asList("Rob", "Fiona", "Jack"))
1324   *
1325   *   raw("name = any(?)", asList("Rob", "Fiona", "Jack"))
1326   *
1327   * }</pre>
1328   *
1329   * <h4>Subquery examples:</h4>
1330   * <pre>{@code
1331   *
1332   *   // Bind collection using ?1
1333   *   .raw("id in (select c.id from o_customer c where c.name in (?1))", asList("Rob", "Fiona", "Jack"))
1334   *
1335   *   // Using Postgres ANY expression
1336   *   .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
1337   *
1338   * }</pre>
1339   */
1340  ExpressionList<T> raw(String raw, Object value);
1341
1342  /**
1343   * Add raw expression with an array of parameters.
1344   * <p>
1345   * The raw expression should contain the same number of ? or ?1, ?2 ... bind parameters
1346   * as there are values. We use ?1, ?2 etc when binding a collection for an IN expression.
1347   * <p>
1348   * When properties in the clause are fully qualified as table-column names
1349   * then they are not translated. logical property name names (not fully
1350   * qualified) will still be translated to their physical name.
1351   * </p>
1352   *
1353   * <h4>Examples:</h4>
1354   * <pre>{@code
1355   *
1356   *   raw("unitPrice > ? and product.id > ?", 2, 3)
1357   *
1358   *   raw("(status = ? or (orderDate < ? and shipDate is null) or customer.name like ?)",
1359   *         Order.Status.APPROVED,
1360   *         new Timestamp(System.currentTimeMillis()),
1361   *         "Rob")
1362   *
1363   * }</pre></pre>
1364   */
1365  ExpressionList<T> raw(String raw, Object... values);
1366
1367  /**
1368   * Add raw expression with no parameters.
1369   * <p>
1370   * When properties in the clause are fully qualified as table-column names
1371   * then they are not translated. logical property name names (not fully
1372   * qualified) will still be translated to their physical name.
1373   * </p>
1374   * <pre>{@code
1375   *
1376   *   raw("orderQty < shipQty")
1377   *
1378   * }</pre>
1379   *
1380   * <h4>Subquery example:</h4>
1381   * <pre>{@code
1382   *
1383   *   .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
1384   *
1385   * }</pre>
1386   */
1387  ExpressionList<T> raw(String raw);
1388
1389  /**
1390   * Only add the raw expression if the values is not null or empty.
1391   * <p>
1392   * This is a pure convenience expression to make it nicer to deal with the pattern where we use
1393   * raw() expression with a subquery and only want to add the subquery predicate when the collection
1394   * of values is not empty.
1395   * </p>
1396   * <h3>Without inOrEmpty()</h3>
1397   * <pre>{@code
1398   *
1399   *   query.where() // add some predicates
1400   *     .eq("status", Status.NEW);
1401   *
1402   *   // common pattern - we can use rawOrEmpty() instead
1403   *   if (orderIds != null && !orderIds.isEmpty()) {
1404   *     query.where().raw("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
1405   *   }
1406   *
1407   *   query.findList();
1408   *
1409   * }</pre>
1410   *
1411   * <h3>Using rawOrEmpty()</h3>
1412   * Note that in the example below we use the <code>?1</code> bind parameter to get  "parameter expansion"
1413   * for each element in the collection.
1414   *
1415   * <pre>{@code
1416   *
1417   *   query.where()
1418   *     .eq("status", Status.NEW)
1419   *     // only add the expression if orderIds is not empty
1420   *     .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
1421   *     .findList();
1422   *
1423   * }</pre>
1424   *
1425   * <h3>Postgres ANY</h3>
1426   * With Postgres we would often use the SQL <code>ANY</code> expression and array parameter binding
1427   * rather than <code>IN</code>.
1428   *
1429   * <pre>{@code
1430   *
1431   *   query.where()
1432   *     .eq("status", Status.NEW)
1433   *     .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id = any(?))", orderIds);
1434   *     .findList();
1435   *
1436   * }</pre>
1437   * <p>
1438   * Note that we need to cast the Postgres array for UUID types like:
1439   * </p>
1440   * <pre>{@code
1441   *
1442   *   " ... = any(?::uuid[])"
1443   *
1444   * }</pre>
1445   *
1446   * @param raw    The raw expression that is typically a subquery
1447   * @param values The values which is typically a list or set of id values.
1448   */
1449  ExpressionList<T> rawOrEmpty(String raw, Collection<?> values);
1450
1451  /**
1452   * Add a match expression.
1453   *
1454   * @param propertyName The property name for the match
1455   * @param search       The search value
1456   */
1457  ExpressionList<T> match(String propertyName, String search);
1458
1459  /**
1460   * Add a match expression with options.
1461   *
1462   * @param propertyName The property name for the match
1463   * @param search       The search value
1464   */
1465  ExpressionList<T> match(String propertyName, String search, Match options);
1466
1467  /**
1468   * Add a multi-match expression.
1469   */
1470  ExpressionList<T> multiMatch(String search, String... properties);
1471
1472  /**
1473   * Add a multi-match expression using options.
1474   */
1475  ExpressionList<T> multiMatch(String search, MultiMatch options);
1476
1477  /**
1478   * Add a simple query string expression.
1479   */
1480  ExpressionList<T> textSimple(String search, TextSimple options);
1481
1482  /**
1483   * Add a query string expression.
1484   */
1485  ExpressionList<T> textQueryString(String search, TextQueryString options);
1486
1487  /**
1488   * Add common terms expression.
1489   */
1490  ExpressionList<T> textCommonTerms(String search, TextCommonTerms options);
1491
1492  /**
1493   * And - join two expressions with a logical and.
1494   */
1495  ExpressionList<T> and(Expression expOne, Expression expTwo);
1496
1497  /**
1498   * Or - join two expressions with a logical or.
1499   */
1500  ExpressionList<T> or(Expression expOne, Expression expTwo);
1501
1502  /**
1503   * Negate the expression (prefix it with NOT).
1504   */
1505  ExpressionList<T> not(Expression exp);
1506
1507  /**
1508   * Start a list of expressions that will be joined by AND's
1509   * returning the expression list the expressions are added to.
1510   * <p>
1511   * This is exactly the same as conjunction();
1512   * </p>
1513   * <p>
1514   * Use endAnd() or endJunction() to end the AND junction.
1515   * </p>
1516   * <p>
1517   * Note that a where() clause defaults to an AND junction so
1518   * typically you only explicitly need to use the and() junction
1519   * when it is nested inside an or() or not() junction.
1520   * </p>
1521   * <pre>{@code
1522   *
1523   *  // Example: Nested and()
1524   *
1525   *    .where()
1526   *    .or()
1527   *      .and() // nested and
1528   *        .startsWith("name", "r")
1529   *        .eq("anniversary", onAfter)
1530   *        .endAnd()
1531   *      .and()
1532   *        .eq("status", Customer.Status.ACTIVE)
1533   *        .gt("id", 0)
1534   *        .endAnd()
1535   *      .order().asc("name")
1536   *      .findList();
1537   * }</pre>
1538   */
1539  Junction<T> and();
1540
1541  /**
1542   * Return a list of expressions that will be joined by OR's.
1543   * This is exactly the same as disjunction();
1544   * <p>
1545   * Use endOr() or endJunction() to end the OR junction.
1546   * </p>
1547   *
1548   * <pre>{@code
1549   *
1550   *  // Example: (status active OR anniversary is null)
1551   *
1552   *    .where()
1553   *    .or()
1554   *      .eq("status", Customer.Status.ACTIVE)
1555   *      .isNull("anniversary")
1556   *    .order().asc("name")
1557   *    .findList();
1558   *
1559   * }</pre>
1560   *
1561   * <pre>{@code
1562   *
1563   *  // Example: Use or() to join
1564   *  // two nested and() expressions
1565   *
1566   *    .where()
1567   *    .or()
1568   *      .and()
1569   *        .startsWith("name", "r")
1570   *        .eq("anniversary", onAfter)
1571   *        .endAnd()
1572   *      .and()
1573   *        .eq("status", Customer.Status.ACTIVE)
1574   *        .gt("id", 0)
1575   *        .endAnd()
1576   *      .order().asc("name")
1577   *      .findList();
1578   *
1579   * }</pre>
1580   */
1581  Junction<T> or();
1582
1583  /**
1584   * Return a list of expressions that will be wrapped by NOT.
1585   * <p>
1586   * Use endNot() or endJunction() to end expressions being added to the
1587   * NOT expression list.
1588   * </p>
1589   *
1590   * <pre>{@code
1591   *
1592   *    .where()
1593   *      .not()
1594   *        .gt("id", 1)
1595   *        .eq("anniversary", onAfter)
1596   *        .endNot()
1597   *
1598   * }</pre>
1599   *
1600   * <pre>{@code
1601   *
1602   * // Example: nested not()
1603   *
1604   *   .where()
1605   *     .eq("status", Customer.Status.ACTIVE)
1606   *     .not()
1607   *       .gt("id", 1)
1608   *       .eq("anniversary", onAfter)
1609   *       .endNot()
1610   *     .order()
1611   *       .asc("name")
1612   *     .findList();
1613   *
1614   * }</pre>
1615   */
1616  Junction<T> not();
1617
1618  /**
1619   * Start (and return) a list of expressions that will be joined by AND's.
1620   * <p>
1621   * This is the same as and().
1622   * </p>
1623   */
1624  Junction<T> conjunction();
1625
1626  /**
1627   * Start (and return) a list of expressions that will be joined by OR's.
1628   * <p>
1629   * This is the same as or().
1630   * </p>
1631   */
1632  Junction<T> disjunction();
1633
1634  /**
1635   * Start a list of expressions that will be joined by MUST.
1636   * <p>
1637   * This automatically makes the query a useDocStore(true) query that
1638   * will execute against the document store (ElasticSearch etc).
1639   * </p>
1640   * <p>
1641   * This is logically similar to and().
1642   * </p>
1643   */
1644  Junction<T> must();
1645
1646  /**
1647   * Start a list of expressions that will be joined by SHOULD.
1648   * <p>
1649   * This automatically makes the query a useDocStore(true) query that
1650   * will execute against the document store (ElasticSearch etc).
1651   * </p>
1652   * <p>
1653   * This is logically similar to or().
1654   * </p>
1655   */
1656  Junction<T> should();
1657
1658  /**
1659   * Start a list of expressions that will be joined by MUST NOT.
1660   * <p>
1661   * This automatically makes the query a useDocStore(true) query that
1662   * will execute against the document store (ElasticSearch etc).
1663   * </p>
1664   * <p>
1665   * This is logically similar to not().
1666   * </p>
1667   */
1668  Junction<T> mustNot();
1669
1670  /**
1671   * End a junction returning the parent expression list.
1672   * <p>
1673   * Ends a and(), or(), not(), must(), mustNot() or should() junction
1674   * such that you get the parent expression.
1675   * </p>
1676   * <p>
1677   * Alternatively you can always use where() to return the top level expression list.
1678   * </p>
1679   */
1680  ExpressionList<T> endJunction();
1681
1682  /**
1683   * End a AND junction - synonym for endJunction().
1684   */
1685  ExpressionList<T> endAnd();
1686
1687  /**
1688   * End a AND junction - synonym for endJunction().
1689   */
1690  ExpressionList<T> endOr();
1691
1692  /**
1693   * End a NOT junction - synonym for endJunction().
1694   */
1695  ExpressionList<T> endNot();
1696
1697}