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