All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cds.ql.cqn.Modifier Maven / Gradle / Ivy

There is a newer version: 3.6.1
Show newest version
/************************************************************************
 * © 2021-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 ************************************************************************/
package com.sap.cds.ql.cqn;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.google.common.annotations.Beta;
import com.sap.cds.ql.BooleanFunction;
import com.sap.cds.ql.CQL;
import com.sap.cds.ql.FilterableStatement;
import com.sap.cds.ql.Predicate;
import com.sap.cds.ql.Select;
import com.sap.cds.ql.StructuredType;
import com.sap.cds.ql.Then;
import com.sap.cds.ql.Value;
import com.sap.cds.ql.cqn.CqnCaseExpression.Case;

/**
 * Provider interface for modifying CQN {@link CqnPredicate Predicates},
 * {@link CqnValue Values} and {@link CqnStatement Statements} copied with
 * {@link CQL#copy(CqnStatement, Modifier) CQL.copy}.
 * 
 * Override the default methods to replace specific parts of the statement /
 * predicate.
 */
public interface Modifier {

	/**
	 * Override this method to replace a {@link CqnStructuredTypeRef structured type
	 * ref}.
	 * 
	 * @param ref the immutable {@link CqnStructuredTypeRef}
	 * @return the replacement ref
	 * 
	 * @see CQL#to(List) CQL.to(segments).asRef() to create a new ref
	 * @see CQL#copy(CqnStructuredTypeRef) CQL.copy(ref) to create a modifiable copy
	 *      of the ref
	 */
	default CqnStructuredTypeRef ref(CqnStructuredTypeRef ref) {
		return ref;
	}

	/**
	 * Override this method to replace an {@link CqnElementRef element} ref with
	 * another {@link CqnValue}.
	 * 
	 * @param ref the immutable {@link CqnElementRef}
	 * @return a {@link CqnValue value} replacing the ref
	 * 
	 * @see CQL#get(List) CQL.get(segments) to create a new ref
	 * @see CQL#copy(CqnElementRef) CQL.copy(ref) to create a modifiable copy of the
	 *      ref
	 */
	default CqnValue ref(CqnElementRef ref) {
		return ref;
	}

	/**
	 * Override this method to replace a {@link CqnLiteral literal} value with
	 * another {@link CqnValue}.
	 * 
	 * @param value the immutable {@link CqnLiteral} value
	 * @return a {@link CqnValue value} replacing the {@link CqnLiteral}
	 * 
	 * @see CQL#val
	 * @see CQL#constant
	 */
	default CqnValue literal(CqnLiteral value) {
		return value;
	}

	/**
	 * Override this method to replace {@link CqnParameter parameters}.
	 * 
	 * @param param the {@link CqnParameter}
	 * @return a {@link CqnValue} replacing the {@code parameter}
	 */
	default CqnValue parameter(CqnParameter param) {
		return param;
	}

	@Beta
	default CqnValue plain(CqnPlain plain) {
		return plain;
	}

	/**
	 * Override this method to replace a {@link CqnListValue list} value with
	 * another {@link CqnValue}.
	 * 
	 * @param values the list of {@link CqnValue values}
	 * @return a {@link CqnValue} replacing the {@link CqnListValue}
	 * 
	 * @see CQL#list
	 */
	default CqnValue list(List> values) {
		return CQL.list(values);
	}

	/**
	 * Override this method to replace an {@link CqnArithmeticExpression arithmetic}
	 * expression.
	 *
	 * @param left  the left-hand side of the expression
	 * @param op    the operator
	 * @param right the right-hand side of the expression
	 * @param type  the return type of the expression
	 * @return a {@link CqnValue} replacing the arithmetic expression
	 * 
	 * @see CQL#expression
	 */
	default CqnValue expression(Value left, CqnArithmeticExpression.Operator op, Value right,
			String type) {
		return CQL.expression(left, op, right).type(type);
	}

	/**
	 * Override this method to replace an {@link CqnCaseExpression case}
	 * expression.
	 *
	 * @param cases the cases
	 * @param defaultValue the default value
	 * @param type the return type of the expression 
	 * @return a {@link CqnValue} replacing the case expression
	 */
	@Beta
	default CqnValue caseExpression(List cases, CqnValue defaultValue, String type) {
		Then builder = CQL.cases();
		for (Case c : cases) {
			builder = builder.when(c.condition()).then(c.value());
		}

		return builder.orElse(defaultValue).type(type);
	}

	/**
	 * Override this method to replace a {@link CqnFunc function} call.
	 *
	 * @param name the name of the function
	 * @param args the arguments of the function
	 * @param type the return type of the function call
	 * @return a {@link CqnValue} replacing the function call
	 * 
	 * @see CQL#func
	 */
	default CqnValue function(String name, List> args, String type) {
		return CQL.func(name, args).type(type);
	}

	/**
	 * Override this method to replace a predicate {@link BooleanFunction function}
	 * call.
	 *
	 * @param name the name of the function
	 * @param args the arguments of the function
	 * @return a {@link CqnPredicate} replacing the Boolean function call
	 * 
	 * @see CQL#booleanFunc
	 */
	default CqnPredicate booleanFunction(String name, List> args) {
		return CQL.booleanFunc(name, args);
	}

	/**
	 * Override this method to replace a {@link CqnComparisonPredicate comparison}
	 * predicate.
	 *
	 * @param lhs the left-hand side of the comparison
	 * @param op  the comparison operator
	 * @param rhs the right-hand side of the comparison
	 * @return a {@link CqnPredicate} replacing the comparison
	 * 
	 * @see CQL#comparison
	 */
	default CqnPredicate comparison(Value lhs, CqnComparisonPredicate.Operator op, Value rhs) {
		return CQL.comparison(lhs, op, rhs);
	}

	/**
	 * Override this method to replace an {@link CqnInPredicate in} predicate that
	 * checks if the given {@code value} is equal to any value in the
	 * {@code valueSet}.
	 * 
	 * @param value    the value to be checked if it's contained in the set
	 * @param valueSet the {@link CqnInPredicate#valueSet() value set}
	 * @return a {@link CqnPredicate} replacing the {@link CqnInPredicate}
	 * 
	 * @see CQL#in
	 */
	default CqnPredicate in(Value value, CqnValue valueSet) {
		return CQL.in(value, valueSet);
	}

	/**
	 * Override this method to replace an {@link CqnInSubquery in subquery}
	 * predicate that checks if the given {@code value} is equal to any value
	 * returned by the subquery.
	 * 
	 * @param inSubquery
	 *            the in subquery predicate
	 * @return a {@link CqnPredicate} replacing the {@link CqnInSubquery}
	 */
	@Beta
	default CqnPredicate in(CqnInSubquery inSubquery) {
		return inSubquery;
	}

	/**
	 * Override this method to replace a {@link CqnBetweenPredicate between}
	 * predicate that that tests if this {@code value} is within a closed interval
	 * with given bounds of {@code low} and {@code high}.
	 * 
	 * @param value the value to be checked if it's contained in a closed interval
	 * @param low   the lower bound
	 * @param high  the upper bound
	 * @return a {@link CqnPredicate} replacing the {@link CqnBetweenPredicate}
	 * 
	 * @see CQL#between
	 */
	default CqnPredicate between(CqnValue value, CqnValue low, CqnValue high) {
		return CQL.between(value, low, high);
	}

	/**
	 * Override this method to replace a {@link CqnPredicate eTag} predicate that
	 * checks if an ETag matches any value from the given {@code values} list.
	 * 
	 * @param values the list of values
	 * @return a {@link CqnPredicate} replacing the {@link CqnEtagPredicate}
	 */
	@Beta
	default CqnPredicate eTag(CqnElementRef ref, CqnListValue values) {
		return CQL.eTag(ref, values);
	}

	/**
	 * Override this method to replace a logical {@link CqnConnectivePredicate
	 * connection} predicate, which connects multiple predicates with the given
	 * {@link CqnConnectivePredicate.Operator operator}.
	 * 
	 * @param op         the connective operator ({@code AND}/{@code OR})
	 * @param predicates the list of connected predicates
	 * @return a {@link CqnPredicate} replacing the logical connection
	 * 
	 * @see CQL#connect
	 * @see CQL#and
	 * @see CQL#or
	 */
	default CqnPredicate connective(CqnConnectivePredicate.Operator op, List predicates) {
		return CQL.connect(op, predicates);
	}

	/**
	 * Override this method to replace a logical {@link CqnNegation negation}.
	 * 
	 * @param predicate the {@link CqnNegation#predicate() predicate} of the
	 *                  negation
	 * @return a {@link CqnPredicate} replacing the negation
	 * 
	 * @see CQL#not
	 */
	default CqnPredicate negation(Predicate predicate) {
		return CQL.not(predicate);
	}

	/**
	 * Override this method to replace an {@link CqnExistsSubquery exist} subquery.
	 * 
	 * @param subQuery the {@link CqnExistsSubquery#subquery() query} of the exists
	 *                 predicate
	 * @return a {@link CqnPredicate} replacing the {@link CqnExistsSubquery}
	 * 
	 * @see CQL#exists
	 */
	default CqnPredicate exists(Select subQuery) {
		return CQL.exists(subQuery);
	}

	/**
	 * Override this method to replace a {@link CqnMatchPredicate match} predicate.
	 * 
	 * @param match the {@code match} predicate
	 * @return a {@link CqnPredicate} replacing the {@link CqnMatchPredicate}
	 * 
	 * @see CQL#match
	 */
	default CqnPredicate match(CqnMatchPredicate match) {
		return match;
	}

	/**
	 * Override this method to replace a {@link CqnContainmentTest containment} test
	 * predicate.
	 * 
	 * @param position        the {@link CqnContainmentTest#position() position}
	 * @param value           the string {@link CqnContainmentTest#value() value}
	 * @param term            the {@link CqnContainmentTest#term() term} to test for
	 * @param caseInsensitive whether the test should be
	 *                        {@link CqnContainmentTest#caseInsensitive() case
	 *                        insensitive}
	 * @return a {@link CqnPredicate} replacing the {@link CqnContainmentTest}
	 * 
	 * @see CQL#containment
	 */
	default CqnPredicate containment(CqnContainmentTest.Position position, CqnValue value, CqnValue term,
			boolean caseInsensitive) {
		return CQL.containment(position, value, term, caseInsensitive);
	}

	/**
	 * Override this method to replace a {@link CqnSearchTermPredicate search}
	 * predicate.
	 * 
	 * @param search the search term predicate
	 * @return a {@link CqnPredicate} replacing the {@link CqnSearchTermPredicate}
	 * 
	 * @see CQL#search
	 */
	default CqnPredicate searchTerm(CqnSearchTermPredicate search) {
		return search(search.searchTerm());
	}

	/**
	 * @deprecated use {@link #searchTerm(CqnSearchTermPredicate)} instead
	 */
	@Deprecated(since = "3.0", forRemoval = true)
	default CqnPredicate search(String term) {
		return CQL.search(term);
	}

	/**
	 * Override this method to replace a {@link CqnPassThroughSearchPredicate search}
	 * predicate.
	 * 
	 * @param search the pass-through search predicate
	 * @return a {@link CqnPredicate} replacing the {@link CqnPassThroughSearchPredicate}
	 */
	default CqnPredicate passThroughSearch(CqnPassThroughSearchPredicate search) {
		return search;
	}

	/*
	 * Select modifier methods.
	 */

	/**
	 * Override this method to set the {@link FilterableStatement#where() where}
	 * clause of {@link FilterableStatement filterable} statements.
	 * 
	 * @param where the {@code where} clause of the statement, or null
	 * @return a {@link CqnPredicate} replacing the where clause
	 */
	default CqnPredicate where(Predicate where) {
		return where;
	}

	/**
	 * Override this method to set the {@link CqnSelect#search() search} clause of
	 * {@link CqnSelect Select} statements.
	 * 
	 * @param search the {@code search} clause of the statement, or null
	 * @return a {@link CqnPredicate} replacing the search clause
	 */
	default CqnPredicate search(Predicate search) {
		return search;
	}

	/**
	 * Override this method to set the
	 * {@link Select#search(java.util.function.Function, Iterable) searchable}
	 * elements of {@link CqnSelect Select} statements.
	 * 
	 * @param searchableElements the searchable elements of the statement
	 * @return the set of searchable elements
	 */
	default Set searchableElements(Set searchableElements) {
		return searchableElements;
	}

	/**
	 * Override this method to replace {@link CqnInline inline} lists.
	 * 
	 * Use {@link StructuredType#inline(Iterable) CQL.to(segments).inline(items)} to
	 * create a new {@code inline}.
	 * 
	 * @param inline the {@link CqnInline}
	 * @return a {@link CqnSelectListItem} replacing the {@code inline}
	 */
	default CqnSelectListItem inline(CqnInline inline) {
		return inline;
	}

	/**
	 * Override this method to replace {@link CqnExpand expand} lists.
	 * 
	 * To create a new expand, use {@link StructuredType#expand(Iterable)
	 * CQL.to(segments).expand(items)}. To create a modifiable copy of the expand,
	 * use {@link CQL#copy(CqnExpand) CQL.copy(expand)}.
	 * 
	 * @param expand the {@link CqnExpand}
	 * @return a {@link CqnSelectListItem} replacing the {@code expand}
	 */
	default CqnSelectListItem expand(CqnExpand expand) {
		return expand;
	}

	/**
	 * Override this method to replace {@link CqnSelectListValue values} on the
	 * select list of {@link CqnSelect Select} statements.
	 * 
	 * @param value the value
	 * @param alias the alias
	 * @return a {@link CqnSelectListItem} replacing the {@code value}
	 */
	@Beta
	default CqnSelectListItem selectListValue(Value value, String alias) {
		return value.as(alias);
	}

	/**
	 * Override this method to replace {@link CqnStar asterisk} (*) on the select
	 * list of {@link CqnSelect Select} statements.
	 * 
	 * @return a {@link CqnSelectListItem} replacing the {@code asterisk}
	 */
	default List selectAll() {
		return new ArrayList<>(0);
	}

	/**
	 * Override this method to modify the select list {@link CqnSelect#items()
	 * items} of {@link CqnSelect Select} statements.
	 * 
	 * @param items the list of selected {@link CqnSelectListItem items}
	 * @return the new list of items
	 */
	default List items(List items) {
		return items;
	}

	/**
	 * Override this method to modify the {@link CqnSelect#excluding() exclude list}
	 * of {@link CqnSelect Select} statements.
	 * 
	 * @param excluding the names of the excluded elements
	 * @return a set of names to be excluded from the Select result
	 */
	default Set excluding(Set excluding) {
		return excluding;
	}

	/**
	 * Override this method to modify the {@link CqnSelect#groupBy() groupBy} clause
	 * of {@link CqnSelect Select} statements.
	 * 
	 * @param values the groupBy list of the Select statement
	 * @return a list of values to group by
	 */
	default List groupBy(List values) {
		return values;
	}

	/**
	 * Override this method to modify the {@link CqnSelect#having() having} clause
	 * of {@link CqnSelect Select} statements.
	 * 
	 * @param having the having clause of the Select statement
	 * @return a {@link Predicate} replacing the having clause
	 */
	@Beta
	default CqnPredicate having(Predicate having) {
		return having;
	}

	/**
	 * Override this method to modify the {@link CqnSelect#orderBy() orderBy} clause
	 * of {@link CqnSelect Select} statements.
	 * 
	 * @param sortSpecs the orderBy list of the Select statement
	 * @return a list of {@link CqnSortSpecification} defining the order of the
	 *         result
	 */
	default List orderBy(List sortSpecs) {
		return sortSpecs;
	}

	/**
	 * Override this method to replace specific {@link CqnSortSpecification sort}
	 * specs in the {@link CqnSelect#orderBy() orderBy} clause of {@link CqnSelect
	 * Select} statements.
	 * 
	 * @param value the value of the sort spec
	 * @param order the sort {@link CqnSortSpecification.Order order}
	 * @return a sort spec
	 * 
	 * @see CQL#sort
	 */
	default CqnSortSpecification sort(Value value, CqnSortSpecification.Order order) {
		return CQL.sort(value, order);
	}

	/**
	 * Override this method to set the {@link CqnSelect#isDistinct() distinct} flag
	 * of {@link CqnSelect Select} statements.
	 * 
	 * @param distinct the {@code distinct} flag of the Select statement
	 * @return the new {@code distinct} flag
	 */
	default boolean distinct(boolean distinct) {
		return distinct;
	}

	/**
	 * Override this method to set the {@link CqnSelect#hasInlineCount() inline
	 * count} flag of {@link CqnSelect Select} statements.
	 * 
	 * @param inlineCount the {@code inline count} flag of the Select statement
	 * @return the new {@code inline count} flag
	 */
	default boolean inlineCount(boolean inlineCount) {
		return inlineCount;
	}

	/**
	 * Override this method to set the {@link Select#limit(long) top} limit of
	 * {@link CqnSelect Select} statements.
	 * 
	 * @param top the {@code top} limit of the Select statement
	 * @return the new maximum number of rows to be selected or -1 for unlimited
	 */
	default long top(long top) {
		return top;
	}

	/**
	 * Override this method to set {@link Select#limit(long, long) skip} of
	 * {@link CqnSelect Select} statements.
	 * 
	 * @param skip the {@code skip} number of the Select statement
	 * @return the new number of rows that shall be skipped
	 */
	default long skip(long skip) {
		return skip;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy