package com.avaje.ebeaninternal.server.expression; import com.avaje.ebean.Expression; import com.avaje.ebean.ExpressionList; import com.avaje.ebean.FetchPath; import com.avaje.ebean.FutureIds; import com.avaje.ebean.FutureList; import com.avaje.ebean.FutureRowCount; import com.avaje.ebean.Junction; import com.avaje.ebean.OrderBy; import com.avaje.ebean.PagedList; import com.avaje.ebean.Query; import com.avaje.ebean.QueryEachConsumer; import com.avaje.ebean.QueryEachWhileConsumer; import com.avaje.ebean.QueryIterator; import com.avaje.ebean.Version; import com.avaje.ebean.event.BeanQueryRequest; import com.avaje.ebean.search.Match; import com.avaje.ebean.search.MultiMatch; import com.avaje.ebean.search.TextCommonTerms; import com.avaje.ebean.search.TextQueryString; import com.avaje.ebean.search.TextSimple; import com.avaje.ebeaninternal.api.HashQueryPlanBuilder; import com.avaje.ebeaninternal.api.ManyWhereJoins; import com.avaje.ebeaninternal.api.SpiExpression; import com.avaje.ebeaninternal.api.SpiExpressionRequest; import com.avaje.ebeaninternal.api.SpiExpressionValidation; import com.avaje.ebeaninternal.api.SpiJunction; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; import java.io.IOException; import java.sql.Timestamp; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; /** * Junction implementation. */ class JunctionExpression implements SpiJunction, SpiExpression, ExpressionList { protected final DefaultExpressionList exprList; protected final Junction.Type type; JunctionExpression(Junction.Type type, Query query, ExpressionList parent) { this.type = type; this.exprList = new DefaultExpressionList(query, parent); } /** * Construct for copyForPlanKey. */ JunctionExpression(Junction.Type type, DefaultExpressionList exprList) { this.type = type; this.exprList = exprList; } public SpiExpression copyForPlanKey() { return new JunctionExpression(type, exprList.copyForPlanKey()); } @Override public void writeDocQuery(DocQueryContext context) throws IOException { context.startBool(type == Type.AND); List list = exprList.internalList(); for (int i = 0; i < list.size(); i++) { list.get(i).writeDocQuery(context); } context.endBool(); } @Override public void writeDocQueryJunction(DocQueryContext context) throws IOException { context.startBoolGroupList(type); List list = exprList.internalList(); for (int i = 0; i < list.size(); i++) { list.get(i).writeDocQuery(context); } context.endBoolGroupList(); } @Override public void containsMany(BeanDescriptor desc, ManyWhereJoins manyWhereJoin) { List list = exprList.internalList(); // get the current state for 'require outer joins' boolean parentOuterJoins = manyWhereJoin.isRequireOuterJoins(); if (type == Type.OR) { // turn on outer joins required for disjunction expressions manyWhereJoin.setRequireOuterJoins(true); } for (int i = 0; i < list.size(); i++) { list.get(i).containsMany(desc, manyWhereJoin); } if (type == Type.OR && !parentOuterJoins) { // restore state to not forcing outer joins manyWhereJoin.setRequireOuterJoins(false); } } @Override public void validate(SpiExpressionValidation validation) { exprList.validate(validation); } @Override public Junction add(Expression item) { exprList.add(item); return this; } @Override public Junction addAll(ExpressionList addList) { exprList.addAll(addList); return this; } @Override public void addBindValues(SpiExpressionRequest request) { List list = exprList.internalList(); for (int i = 0; i < list.size(); i++) { list.get(i).addBindValues(request); } } @Override public void addSql(SpiExpressionRequest request) { List list = exprList.internalList(); if (!list.isEmpty()) { request.append(type.prefix()); request.append("("); for (int i = 0; i < list.size(); i++) { SpiExpression item = list.get(i); if (i > 0) { request.append(type.literal()); } item.addSql(request); } request.append(") "); } } @Override public void prepareExpression(BeanQueryRequest request) { List list = exprList.internalList(); for (int i = 0; i < list.size(); i++) { list.get(i).prepareExpression(request); } } /** * Based on Junction type and all the expression contained. */ @Override public void queryPlanHash(HashQueryPlanBuilder builder) { builder.add(JunctionExpression.class).add(type); List list = exprList.internalList(); for (int i = 0; i < list.size(); i++) { list.get(i).queryPlanHash(builder); } } @Override public int queryBindHash() { int hc = JunctionExpression.class.getName().hashCode(); List list = exprList.internalList(); for (int i = 0; i < list.size(); i++) { hc = hc * 31 + list.get(i).queryBindHash(); } return hc; } @Override public boolean isSameByPlan(SpiExpression other) { if (!(other instanceof JunctionExpression)) { return false; } JunctionExpression that = (JunctionExpression) other; return type == that.type && exprList.isSameByPlan(that.exprList); } @Override public boolean isSameByBind(SpiExpression other) { JunctionExpression that = (JunctionExpression) other; return type == that.type && exprList.isSameByBind(that.exprList); } @Override public ExpressionList match(String propertyName, String search) { return match(propertyName, search, null); } @Override public ExpressionList match(String propertyName, String search, Match options) { return exprList.match(propertyName, search, options); } @Override public ExpressionList multiMatch(String query, String... properties) { return exprList.multiMatch(query, properties); } @Override public ExpressionList multiMatch(String query, MultiMatch options) { return exprList.multiMatch(query, options); } @Override public ExpressionList textSimple(String search, TextSimple options) { return exprList.textSimple(search, options); } @Override public ExpressionList textQueryString(String search, TextQueryString options) { return exprList.textQueryString(search, options); } @Override public ExpressionList textCommonTerms(String search, TextCommonTerms options) { return exprList.textCommonTerms(search, options); } @Override public ExpressionList allEq(Map propertyMap) { return exprList.allEq(propertyMap); } @Override public ExpressionList and(Expression expOne, Expression expTwo) { return exprList.and(expOne, expTwo); } @Override public ExpressionList between(String propertyName, Object value1, Object value2) { return exprList.between(propertyName, value1, value2); } @Override public ExpressionList betweenProperties(String lowProperty, String highProperty, Object value) { return exprList.betweenProperties(lowProperty, highProperty, value); } @Override public ExpressionList contains(String propertyName, String value) { return exprList.contains(propertyName, value); } @Override public ExpressionList endsWith(String propertyName, String value) { return exprList.endsWith(propertyName, value); } @Override public ExpressionList eq(String propertyName, Object value) { return exprList.eq(propertyName, value); } @Override public ExpressionList exampleLike(Object example) { return exprList.exampleLike(example); } @Override public ExpressionList filterMany(String prop) { throw new RuntimeException("filterMany not allowed on Junction expression list"); } @Override public int delete() { return exprList.delete(); } @Override public Query asOf(Timestamp asOf) { return exprList.asOf(asOf); } @Override public Query asDraft() { return exprList.asDraft(); } @Override public Query includeSoftDeletes() { return exprList.includeSoftDeletes(); } @Override public List> findVersions() { return exprList.findVersions(); } @Override public List> findVersionsBetween(Timestamp start, Timestamp end) { return exprList.findVersionsBetween(start, end); } @Override public Query apply(FetchPath fetchPath) { return exprList.apply(fetchPath); } @Override public FutureIds findFutureIds() { return exprList.findFutureIds(); } @Override public FutureList findFutureList() { return exprList.findFutureList(); } @Override public FutureRowCount findFutureRowCount() { return exprList.findFutureRowCount(); } @Override public List findIds() { return exprList.findIds(); } @Override public void findEach(QueryEachConsumer consumer) { exprList.findEach(consumer); } @Override public void findEachWhile(QueryEachWhileConsumer consumer) { exprList.findEachWhile(consumer); } @Override public QueryIterator findIterate() { return exprList.findIterate(); } @Override public List findList() { return exprList.findList(); } @Override public Map findMap() { return exprList.findMap(); } @Override public Map findMap(String keyProperty, Class keyType) { return exprList.findMap(keyProperty, keyType); } @Override public PagedList findPagedList(int pageIndex, int pageSize) { return exprList.findPagedList(pageIndex, pageSize); } @Override public PagedList findPagedList() { return exprList.findPagedList(); } @Override public int findRowCount() { return exprList.findRowCount(); } @Override public Set findSet() { return exprList.findSet(); } @Override public T findUnique() { return exprList.findUnique(); } /** * Path exists - for the given path in a JSON document. */ @Override public ExpressionList jsonExists(String propertyName, String path) { return exprList.jsonExists(propertyName, path); } /** * Path does not exist - for the given path in a JSON document. */ @Override public ExpressionList jsonNotExists(String propertyName, String path){ return exprList.jsonNotExists(propertyName, path); } /** * Equal to - for the value at the given path in the JSON document. */ @Override public ExpressionList jsonEqualTo(String propertyName, String path, Object value){ return exprList.jsonEqualTo(propertyName, path, value); } /** * Not Equal to - for the given path in a JSON document. */ @Override public ExpressionList jsonNotEqualTo(String propertyName, String path, Object val){ return exprList.jsonNotEqualTo(propertyName, path, val); } /** * Greater than - for the given path in a JSON document. */ @Override public ExpressionList jsonGreaterThan(String propertyName, String path, Object val){ return exprList.jsonGreaterThan(propertyName, path, val); } /** * Greater than or equal to - for the given path in a JSON document. */ @Override public ExpressionList jsonGreaterOrEqual(String propertyName, String path, Object val){ return exprList.jsonGreaterOrEqual(propertyName, path, val); } /** * Less than - for the given path in a JSON document. */ @Override public ExpressionList jsonLessThan(String propertyName, String path, Object val){ return exprList.jsonLessThan(propertyName, path, val); } /** * Less than or equal to - for the given path in a JSON document. */ @Override public ExpressionList jsonLessOrEqualTo(String propertyName, String path, Object val){ return exprList.jsonLessOrEqualTo(propertyName, path, val); } /** * Between - for the given path in a JSON document. */ @Override public ExpressionList jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue){ return exprList.jsonBetween(propertyName, path, lowerValue, upperValue); } @Override public ExpressionList ge(String propertyName, Object value) { return exprList.ge(propertyName, value); } @Override public ExpressionList gt(String propertyName, Object value) { return exprList.gt(propertyName, value); } @Override public ExpressionList having() { throw new RuntimeException("having() not allowed on Junction expression list"); } @Override public ExpressionList icontains(String propertyName, String value) { return exprList.icontains(propertyName, value); } @Override public ExpressionList idEq(Object value) { return exprList.idEq(value); } @Override public ExpressionList idIn(List idValues) { return exprList.idIn(idValues); } @Override public ExpressionList iendsWith(String propertyName, String value) { return exprList.iendsWith(propertyName, value); } @Override public ExpressionList ieq(String propertyName, String value) { return exprList.ieq(propertyName, value); } @Override public ExpressionList iexampleLike(Object example) { return exprList.iexampleLike(example); } @Override public ExpressionList ilike(String propertyName, String value) { return exprList.ilike(propertyName, value); } @Override public ExpressionList in(String propertyName, Collection values) { return exprList.in(propertyName, values); } @Override public ExpressionList in(String propertyName, Object... values) { return exprList.in(propertyName, values); } @Override public ExpressionList in(String propertyName, Query subQuery) { return exprList.in(propertyName, subQuery); } @Override public ExpressionList notIn(String propertyName, Collection values) { return exprList.notIn(propertyName, values); } @Override public ExpressionList notIn(String propertyName, Object... values) { return exprList.notIn(propertyName, values); } @Override public ExpressionList notIn(String propertyName, Query subQuery) { return exprList.notIn(propertyName, subQuery); } @Override public ExpressionList exists(Query subQuery) { return exprList.exists(subQuery); } @Override public ExpressionList notExists(Query subQuery) { return exprList.exists(subQuery); } @Override public ExpressionList isNotNull(String propertyName) { return exprList.isNotNull(propertyName); } @Override public ExpressionList isNull(String propertyName) { return exprList.isNull(propertyName); } @Override public ExpressionList istartsWith(String propertyName, String value) { return exprList.istartsWith(propertyName, value); } @Override public ExpressionList le(String propertyName, Object value) { return exprList.le(propertyName, value); } @Override public ExpressionList like(String propertyName, String value) { return exprList.like(propertyName, value); } @Override public ExpressionList lt(String propertyName, Object value) { return exprList.lt(propertyName, value); } @Override public ExpressionList ne(String propertyName, Object value) { return exprList.ne(propertyName, value); } @Override public ExpressionList not(Expression exp) { return exprList.not(exp); } @Override public ExpressionList or(Expression expOne, Expression expTwo) { return exprList.or(expOne, expTwo); } @Override public OrderBy order() { return exprList.order(); } @Override public Query order(String orderByClause) { return exprList.order(orderByClause); } @Override public OrderBy orderBy() { return exprList.orderBy(); } @Override public Query orderBy(String orderBy) { return exprList.orderBy(orderBy); } @Override public Query query() { return exprList.query(); } @Override public ExpressionList raw(String raw, Object value) { return exprList.raw(raw, value); } @Override public ExpressionList raw(String raw, Object... values) { return exprList.raw(raw, values); } @Override public ExpressionList raw(String raw) { return exprList.raw(raw); } @Override public Query select(String properties) { return exprList.select(properties); } @Override public Query setDistinct(boolean distinct) { return exprList.setDistinct(distinct); } @Override public Query setFirstRow(int firstRow) { return exprList.setFirstRow(firstRow); } @Override public Query setMapKey(String mapKey) { return exprList.setMapKey(mapKey); } @Override public Query setMaxRows(int maxRows) { return exprList.setMaxRows(maxRows); } @Override public Query setOrderBy(String orderBy) { return exprList.setOrderBy(orderBy); } @Override public Query setUseCache(boolean useCache) { return exprList.setUseCache(useCache); } @Override public Query setUseQueryCache(boolean useCache) { return exprList.setUseQueryCache(useCache); } @Override public Query setUseDocStore(boolean useDocsStore) { return exprList.setUseDocStore(useDocsStore); } @Override public Query setDisableLazyLoading(boolean disableLazyLoading) { return exprList.setDisableLazyLoading(disableLazyLoading); } @Override public Query setDisableReadAuditing() { return exprList.setDisableReadAuditing(); } @Override public ExpressionList startsWith(String propertyName, String value) { return exprList.startsWith(propertyName, value); } @Override public ExpressionList where() { return exprList.where(); } @Override public Junction and() { return conjunction(); } @Override public Junction or() { return disjunction(); } @Override public Junction not() { return exprList.not(); } @Override public Junction conjunction() { return exprList.conjunction(); } @Override public Junction disjunction() { return exprList.disjunction(); } @Override public Junction must() { return exprList.must(); } @Override public Junction should() { return exprList.should(); } @Override public Junction mustNot() { return exprList.mustNot(); } @Override public ExpressionList endJunction() { return exprList.endJunction(); } @Override public ExpressionList endAnd() { return endJunction(); } @Override public ExpressionList endOr() { return endJunction(); } @Override public ExpressionList endNot() { return endJunction(); } @Override public ExpressionList endMust() { return endJunction(); } @Override public ExpressionList endShould() { return endJunction(); } @Override public ExpressionList endMustNot() { return endJunction(); } }