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

com.sap.cds.ql.CQL Maven / Gradle / Ivy

The newest version!
/************************************************************************
 * © 2020-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 ************************************************************************/
package com.sap.cds.ql;

import static java.util.Arrays.asList;

import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collector;

import com.google.common.annotations.Beta;
import com.sap.cds.ql.cqn.CqnArithmeticExpression;
import com.sap.cds.ql.cqn.CqnBetweenPredicate;
import com.sap.cds.ql.cqn.CqnCaseExpression;
import com.sap.cds.ql.cqn.CqnComparisonPredicate;
import com.sap.cds.ql.cqn.CqnConnectivePredicate;
import com.sap.cds.ql.cqn.CqnConnectivePredicate.Operator;
import com.sap.cds.ql.cqn.CqnContainmentTest;
import com.sap.cds.ql.cqn.CqnContainmentTest.Position;
import com.sap.cds.ql.cqn.CqnElementRef;
import com.sap.cds.ql.cqn.CqnEtagPredicate;
import com.sap.cds.ql.cqn.CqnExpand;
import com.sap.cds.ql.cqn.CqnInPredicate;
import com.sap.cds.ql.cqn.CqnListValue;
import com.sap.cds.ql.cqn.CqnMatchPredicate;
import com.sap.cds.ql.cqn.CqnPredicate;
import com.sap.cds.ql.cqn.CqnReference.Segment;
import com.sap.cds.ql.cqn.CqnSelect;
import com.sap.cds.ql.cqn.CqnSortSpecification;
import com.sap.cds.ql.cqn.CqnSortSpecification.Order;
import com.sap.cds.ql.cqn.CqnStar;
import com.sap.cds.ql.cqn.CqnStatement;
import com.sap.cds.ql.cqn.CqnStructuredTypeRef;
import com.sap.cds.ql.cqn.CqnValue;
import com.sap.cds.ql.cqn.CqnVector;
import com.sap.cds.ql.cqn.Modifier;

public interface CQL {

	BooleanValue TRUE = CDS.QL.create.booleanValue(true);
	BooleanValue FALSE = CDS.QL.create.booleanValue(false);
	NullValue NULL = CDS.QL.create.nullValue();

	/**
	 * Creates a {@link RefBuilder} from the given ref, which allows for in-place
	 * modification of the ref.
	 *
	 * @param ref the ref to be copied
	 * @return the ref builder
	 */
	static RefBuilder copy(CqnStructuredTypeRef ref) {
		return CDS.QL.builder.copy(ref);
	}

	/**
	 * Creates a {@link RefBuilder} from the given ref, which allows for in-place
	 * modification of the ref.
	 *
	 * @param ref the element ref to be copied
	 * @return the ref builder
	 */
	static RefBuilder> copy(CqnElementRef ref) {
		return CDS.QL.builder.copy(ref);
	}

	/**
	 * Creates a copy of the given expand.
	 *
	 * @param expand the expand to be copied
	 * @return the copy
	 */
	static Expand copy(CqnExpand expand) {
		return CDS.QL.builder.copy(expand);
	}

	/**
	 * Creates a copy of the given predicate.
	 *
	 * @param pred the predicate to be copied
	 * @return the copy
	 */
	static Predicate copy(CqnPredicate pred) {
		return CDS.QL.builder.copy(pred);
	}

	/**
	 * Creates a modified copy of the given predicate.
	 *
	 * @param pred     the predicate to be copied
	 * @param modifier the modifier for altering the copy
	 * @return the modified copy
	 */
	static Predicate copy(CqnPredicate pred, Modifier modifier) {
		return CDS.QL.builder.copy(pred, modifier);
	}

	/**
	 * Creates a copy of the given CQN statement.
	 *
	 * @param        the type of CqnStatement
	 * @param statement the CQN statement to be copied
	 * @return the copy
	 */
	static  S copy(S statement) {
		return CDS.QL.builder.copy(statement);
	}

	/**
	 * Creates a modified copy of the given CQN statement.
	 *
	 * @param        the type of CqnStatement
	 * @param statement the CQN statement to be copied
	 * @param modifier  the modifier for altering the copy
	 * @return the modified copy
	 */
	static  S copy(S statement, Modifier modifier) {
		return CDS.QL.builder.copy(statement, modifier);
	}

	/**
	 * Creates a CDS QL function call that is send to the underlying data store.
	 *
	 * @param   the return type of the function call
	 * @param name the name of the function to be called
	 * @param args the arguments of the function
	 * @return the CDS QL function call
	 */
	static  FunctionCall func(String name, CqnValue... args) {
		return func(name, asList(args));
	}

	/**
	 * Creates a CDS QL function call that is send to the underlying data store.
	 *
	 * @param   the return type of the function call
	 * @param name the name of the function to be called
	 * @param args the arguments of the function
	 * @return the CDS QL function call
	 */
	static  FunctionCall func(String name, List args) {
		return CDS.QL.create.func(name, args);
	}

	/**
	 * Creates a CDS QL function call that is send to the underlying data store.
	 *
	 * @param name the name of the function to be called
	 * @param args the arguments of the function
	 * @return the CDS QL function call
	 */
	static BooleanFunction booleanFunc(String name, List args) {
		return CDS.QL.create.booleanFunc(name, args);
	}

	/**
	 * Creates a {@link Value} of type {@link T} with a hint that the value should
	 * be treated as constant.
	 *
	 * @param    the type of the constant
	 * @param value the value
	 * @return the constant
	 */
	static  Literal constant(T value) {
		return CDS.QL.create.constant(value);
	}

	/**
	 * Creates a {@link Value} of type {@link T}.
	 *
	 * @param    the type of the non-constant value
	 * @param value the value of the non-constant value
	 * @return the value
	 * @see #param(String)
	 */
	static  Literal val(T value) {
		return CDS.QL.create.val(value);
	}

	/**
	 * Creates a new {@link CqnVector} which can be used in vector functions such as
	 * {@link #cosineSimilarity} and {@link #l2Distance}.
	 *
	 * @param vector the vector as float[] or in String format
	 * @return the {@link CqnVector}
	 */
	@Beta
	static CqnVector vector(Object vector) {
		return CDS.QL.create.vector(vector);
	}

	/**
	 * Negates a given {@link CqnPredicate}.
	 *
	 * @param predicate the {@code CqnPredicate} to be negated
	 * @return the negated predicate
	 */
	static Predicate not(CqnPredicate predicate) {
		return CDS.QL.create.not(predicate);
	}

	/**
	 * Creates a conjunction of two given predicates
	 *
	 * @param p1 1st operand of the conjunction
	 * @param p2 2nd operand of the conjunction
	 * @return the conjunction
	 */
	static Predicate and(CqnPredicate p1, CqnPredicate p2) {
		return and(asList(p1, p2));
	}

	/**
	 * Returns a {@link Collector} that connects the input predicates with AND.
	 *
	 * If there are none the {@link Collector} returns TRUE.
	 *
	 * @return the collector
	 */
	static Collector withAnd() {
		return CDS.QL.create.withAnd();
	}

	/**
	 * Creates a disjunction of two given predicates
	 *
	 * @param p1 1st operand of the disjunction
	 * @param p2 2nd operand of the disjunction
	 * @return the disjunction
	 */
	static Predicate or(CqnPredicate p1, CqnPredicate p2) {
		return or(asList(p1, p2));
	}

	/**
	 * Creates a conjunction of given predicates
	 *
	 * @param predicates the predicates to connect
	 * @return the conjunction
	 */
	static Predicate and(Iterable predicates) {
		return connect(Operator.AND, predicates);
	}

	/**
	 * Creates a disjunction of given predicates
	 *
	 * @param predicates the predicates to connect
	 * @return the disjunction
	 */
	static Predicate or(Iterable predicates) {
		return connect(Operator.OR, predicates);
	}

	/**
	 * Returns a {@link Collector} that connects the input predicates with OR.
	 *
	 * If there are none the {@link Collector} returns FALSE.
	 *
	 * @return the collector
	 */
	static Collector withOr() {
		return CDS.QL.create.withOr();
	}

	/**
	 * Creates a logical connection of given predicates {@link CqnPredicate}.
	 *
	 * @param operator   operator to connect the predicates with
	 * @param predicates the predicates to connect
	 * @return the logical connection
	 */
	static Predicate connect(CqnConnectivePredicate.Operator operator, Iterable predicates) {
		return CDS.QL.create.connect(operator, predicates);
	}

	/**
	 * Creates an indexed {@link Parameter} to be used in CQN statements. Can be
	 * used with positional parameter values.
	 *
	 * @param    the type of the parameter
	 * @param index the parameter index. If used with positional parameter values,
	 *              start with 0 for the first parameter
	 * @return the parameter
	 */
	static  Parameter param(int index) {
		return param(String.valueOf(index));
	}

	/**
	 * Creates a named {@link Parameter} to be used in queries.
	 *
	 * @param   the type of the parameter
	 * @param name the parameter name
	 * @return the parameter
	 */
	static  Parameter param(String name) {
		return CDS.QL.create.param(name);
	}

	/**
	 * Creates a CQN plain value, which is directly send to the underlying data
	 * store.
	 *
	 * @param value the value content
	 * @return the plain value
	 */
	static Value plain(String value) {
		return CDS.QL.create.plain(value);
	}

	/**
	 * Creates a count all function call.
	 *
	 * @return the count value
	 */
	static Value count() {
		return func("COUNT");
	}

	/**
	 * Creates a count function call on the given element.
	 *
	 * @param element the ref to the element to be counted
	 * @return the count value
	 */
	static Value count(CqnElementRef element) {
		return func("COUNT", element);
	}

	/**
	 * Creates a min function call on the given element or expression.
	 *
	 * @param    the type of the value
	 * @param value the ref to the element to be counted or an expression
	 * @return the minimum value
	 */
	static  Value min(CqnValue value) {
		return func("min", value);
	}

	/**
	 * Creates a max function call on the given element or expression.
	 *
	 * @param    the type of the value
	 * @param value the ref to the element to be counted or an expression
	 * @return the maximum value
	 */
	static  Value max(CqnValue value) {
		return func("max", value);
	}

	/**
	 * Creates a sum function call on the given element or expression.
	 *
	 * @param value the ref to the element to be counted or an expression
	 * @return the sum value
	 */
	static Value sum(CqnValue value) {
		return func("sum", value);
	}

	/**
	 * Creates an average function call on the given element or expression.
	 *
	 * @param value the ref to the element to be counted or an expression
	 * @return the average value
	 */
	static Value average(CqnValue value) {
		return func("avg", value);
	}

	/**
	 * Creates an count distinct function call on the given element or expression.
	 *
	 * @param value the ref to the element to be counted or an expression
	 * @return the count of distinct values
	 */
	static Value countDistinct(CqnValue value) {
		return CDS.QL.create.countDistinct(value);
	}

	/**
	 * Creates a predicate that tests whether a string value contains a given
	 * substring
	 *
	 * @param value           the string value
	 * @param substring       the substring to test for
	 * @param caseInsensitive whether the test should be case insensitive
	 * @return the predicate for the containment test
	 */
	static Predicate contains(CqnValue value, CqnValue substring, boolean caseInsensitive) {
		return CDS.QL.create.containment(Position.ANY, value, substring, caseInsensitive);
	}

	/**
	 * Creates a predicate that tests whether a string value starts with a given
	 * prefix
	 *
	 * @param value           the string value
	 * @param prefix          the prefix to test for
	 * @param caseInsensitive whether the test should be case insensitive
	 * @return the predicate for the containment test
	 */
	static Predicate startsWith(CqnValue value, CqnValue prefix, boolean caseInsensitive) {
		return CDS.QL.create.containment(Position.START, value, prefix, caseInsensitive);
	}

	/**
	 * Creates a predicate that tests whether a string value ends with a given
	 * suffix
	 *
	 * @param value           the string value
	 * @param suffix          the suffix to test for
	 * @param caseInsensitive whether the test should be case insensitive
	 * @return the predicate for the containment test
	 */
	static Predicate endsWith(CqnValue value, CqnValue suffix, boolean caseInsensitive) {
		return CDS.QL.create.containment(Position.END, value, suffix, caseInsensitive);
	}

	/**
	 * Creates a predicate that tests whether a string value contains a given
	 * substring at a given position {@link CqnContainmentTest.Position}
	 *
	 * @param position        the position
	 * @param value           the string value
	 * @param substring       the substring to test for
	 * @param caseInsensitive whether the test should be case insensitive
	 * @return the predicate for the containment test
	 */
	static Predicate containment(CqnContainmentTest.Position position, CqnValue value, CqnValue substring,
			boolean caseInsensitive) {
		return CDS.QL.create.containment(position, value, substring, caseInsensitive);
	}

	/**
	 * Creates a CDS QL expression for converting the given string value to lower
	 * case using the rules of the underlying data store.
	 *
	 * @param val the String value to be converted
	 * @return the CDS QL expression for lower case conversion
	 */
	static Value toLower(Value val) {
		return CDS.QL.create.toLower(val);
	}

	/**
	 * Creates a CDS QL expression for converting the given string value to lower
	 * case using the rules of the underlying data store.
	 *
	 * @param val the String value to be converted
	 * @return the CDS QL expression for lower case conversion
	 */
	static Value toLower(String val) {
		return CDS.QL.create.toLower(val(val));
	}

	/**
	 * Creates a CDS QL expression for converting the given string value to upper
	 * case using the rules of the underlying data store.
	 *
	 * @param val the String value to be converted
	 * @return the CDS QL expression for upper case conversion
	 */
	static Value toUpper(Value val) {
		return CDS.QL.create.toUpper(val);
	}

	/**
	 * Creates a CDS QL expression for converting the given string value to upper
	 * case using the rules of the underlying data store.
	 *
	 * @param val the String value to be converted
	 * @return the CDS QL expression for upper case conversion
	 */
	static Value toUpper(String val) {
		return CDS.QL.create.toUpper(val(val));
	}

	/**
	 * Creates a CDS QL function to compute the cosine similarity of two vectors.
	 *
	 * @param vector1 the first vector
	 * @param vector2 the second vector
	 * @return the cosine similarity function
	 */
	static Value cosineSimilarity(CqnValue vector1, CqnValue vector2) {
		return CDS.QL.create.cosineSimilarity(vector1, vector2);
	}

	/**
	 * Creates a CDS QL function to compute the L2 distance of two
	 * vectors.
	 *
	 * @param vector1 the first vector
	 * @param vector2 the second vector
	 * @return the L2 distance function
	 */
	static Value l2Distance(CqnValue vector1, CqnValue vector2) {
		return CDS.QL.create.l2Distance(vector1, vector2);
	}

	/**
	 * Creates a {@link StructuredType} representing a CDS entity.
	 *
	 * @param qualifiedName the qualified name of the CDS entity
	 * @return the {@code StructuredType} representing the CDS entity
	 */
	static StructuredType entity(String qualifiedName) {
		return CDS.QL.create.entity(qualifiedName);
	}

	/**
	 * Creates a {@link StructuredType} representing a CDS entity.
	 *
	 * @param   the type of the entity
	 * @param type the class of the entity type
	 * @return the {@code StructuredType} representing the CDS entity
	 */
	static > T entity(Class type) {
		return CDS.QL.create.entity(type);
	}

	/**
	 * Creates a {@link StructuredType} representing a path from a CDS entity to
	 * another entity.
	 *
	 * @param path a String of association element names separated by '.'
	 * @return the {@code StructuredType} representing the path to a CDS entity
	 */
	static StructuredType to(String path) {
		return CDS.QL.create.to(path);
	}

	/**
	 * Creates a {@link StructuredType} representing a path from a CDS entity to
	 * another entity.
	 * 
	 * To create a {@link StructuredTypeRef}, use {@link StructuredType#asRef()
	 * CQL.to(segments).asRef()}.
	 *
	 * @param segments the segments of the path
	 * @return the {@code StructuredType} representing the path to a CDS entity
	 */
	static StructuredType to(List segments) {
		return CDS.QL.create.to(segments);
	}

	/**
	 * Creates an {@link ElementRef} representing a path from a CDS entity to an
	 * element of this or another entity.
	 *
	 * @param   the type of the element
	 * @param path a String of element names separated by '.', where all except the
	 *             last segment represent association elements.
	 * @return the {@code ElementRef} representing the path to the CDS element
	 */
	static  ElementRef get(String path) {
		return CDS.QL.create.get(path);
	}

	/**
	 * Creates an {@link ElementRef} representing a path from a CDS entity to an
	 * element of this or another entity.
	 *
	 * @param       the type of the element
	 * @param segments the segments of the path
	 * @return the {@code ElementRef} representing the path to the CDS element
	 */
	static  ElementRef get(List segments) {
		return CDS.QL.create.get(segments);
	}

	/**
	 * Creates a segment of a structured type or element reference without filter.
	 * 
	 * Use {@link #refSegment(String, CqnPredicate)} to create a segment with filter
	 * condition.
	 *
	 * @param id the id of the segment
	 * @return the segment
	 */
	static Segment refSegment(String id) {
		return CDS.QL.create.refSegment(id);
	}

	/**
	 * Creates a segment of a structured type or element reference with a filter
	 * condition.
	 *
	 * @param id     the id of the segment
	 * @param filter the filter of the segment
	 * @return the segment
	 */
	static Segment refSegment(String id, CqnPredicate filter) {
		return CDS.QL.create.refSegment(id, filter);
	}

	/**
	 * Creates a list of reference segments without filter.
	 *
	 * @param segmentIds the ids of the segments
	 * @return the segments
	 */
	static List refSegments(List segmentIds) {
		return CDS.QL.create.refSegments(segmentIds);
	}

	/**
	 * Creates an arithmetic expression.
	 *
	 * @param left  the left-hand side of the expression
	 * @param op    the operator
	 * @param right the right-hand side of the expression
	 * @return the arithmetic expression
	 */
	static Value expression(CqnValue left, CqnArithmeticExpression.Operator op, CqnValue right) {
		return CDS.QL.create.expression(left, op, right);
	}

	/**
	 * Creates a 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 the comparison predicate
	 */
	static Predicate comparison(CqnValue lhs, CqnComparisonPredicate.Operator op, CqnValue rhs) {
		return CDS.QL.create.comparison(lhs, op, rhs);
	}

	/**
	 * Creates an {@link CqnInPredicate in} predicate.
	 *
	 * @param value  the value to be checked if it's contained in the collection
	 * @param values the collection of values
	 * @return the {@code in} predicate
	 */
	static Predicate in(CqnValue value, Collection values) {
		return CDS.QL.create.in(value, values);
	}

	/**
	 * Creates a {@link CqnBetweenPredicate between} predicate that tests if this
	 * {@code value} is within a closed interval with given bounds
	 *
	 * @param value the value to be checked if it's contained in a closed interval
	 *              between {@code low} and {@code high}
	 * @param low   the lower bound
	 * @param high  the upper bound
	 * @return the {@code between} predicate
	 */
	static Predicate between(CqnValue value, CqnValue low, CqnValue high) {
		return CDS.QL.create.between(value, low, high);
	}

	/**
	 * Creates an {@link CqnInPredicate in} predicate.
	 *
	 * @param value    the value to be checked if it's contained in the collection
	 * @param valueSet the value describing a collection of values
	 * @return the {@code in} predicate
	 */
	static Predicate in(CqnValue value, CqnValue valueSet) {
		return CDS.QL.create.in(value, valueSet);
	}

	/**
	 * Creates a predicate that checks if the values of the given elements match any
	 * of the given value sets.
	 * 
	 * The value sets to test against are computed from the given value maps by
	 * extracting the values for the given elements.
	 *
	 * @param elements  the element names
	 * @param valueMaps the value maps to match against
	 */
	static Predicate in(List elements, Collection> valueMaps) {
		return CDS.QL.create.in(elements, valueMaps);
	}

	/**
	 * Creates an IN predicate that tests if this value is equal to any value
	 * returned by the subquery.
	 *
	 * @param value    the value (n-tuple) to be checked if it's contained in the
	 *                 result of the subquery
	 * @param subquery the subquery that defines the set of expected values
	 * @return the IN predicate
	 */
	static Predicate in(CqnValue value, CqnSelect subquery) {
		return CDS.QL.create.in(value, subquery);
	}

	/**
	 * Creates a {@link CqnEtagPredicate} predicate.
	 * 
	 * @param values the list of ETag values
	 * @return the {@code eTag} predicate
	 */
	@Beta
	static Predicate eTag(CqnListValue values) {
		return CDS.QL.create.eTag(values);
	}

	/**
	 * Creates a {@link CqnEtagPredicate} predicate.
	 * 
	 * @param value the ETag value
	 * @return the {@code eTag} predicate
	 */
	@Beta
	static Predicate eTag(Object value) {
		return eTag(list(val(value)));
	}

	/**
	 * Creates a {@link CqnEtagPredicate} predicate.
	 * 
	 * @param elementRef the reference to ETag element
	 * @param value      the ETag values
	 * @return the {@code eTag} predicate
	 */
	@Beta
	static Predicate eTag(CqnElementRef elementRef, Object value) {
		return CDS.QL.create.eTag(elementRef, value);
	}

	/**
	 * Creates a search predicate.
	 *
	 * @param term the search term
	 * @return the search predicate
	 */
	static Predicate search(String term) {
		return CDS.QL.create.search(term);
	}

	/**
	 * Creates an exists predicate that tests if a given subquery returns any row
	 *
	 * @param subQuery the subquery that performs the existence test
	 * @return the exists predicate
	 */
	static Predicate exists(CqnSelect subQuery) {
		return CDS.QL.create.exists(subQuery);
	}

	/**
	 * Creates a match predicate that tests if a given ref matches a given filter
	 *
	 * @param ref        the reference
	 * @param pred       the filter
	 * @param quantifier all or any
	 * @return the match predicate
	 */
	static Predicate match(CqnStructuredTypeRef ref, CqnPredicate pred, CqnMatchPredicate.Quantifier quantifier) {
		return CDS.QL.create.match(ref, pred, quantifier);
	}

	/**
	 * Creates an {@link ElementRef} to be used in queries to represent $now.
	 *
	 * @return the now value
	 */
	static Value now() {
		return CDS.QL.create.now().type(Instant.class);
	}

	/**
	 * Creates an {@link ElementRef} on the available $validFrom value.
	 *
	 * @return the validFrom value
	 */
	static Value validFrom() {
		return CDS.QL.create.validFrom().type(Instant.class);
	}

	/**
	 * Creates an {@link ElementRef} on the available $validTo value.
	 *
	 * @return the validTo value
	 */
	static Value validTo() {
		return CDS.QL.create.validTo().type(Instant.class);
	}

	/**
	 * Creates an {@link ElementRef} on the available $user.locale value.
	 *
	 * @return the locale string value
	 */
	static Value userLocale() {
		return CDS.QL.create.userLocale().type(String.class);
	}

	/**
	 * Creates an {@link ElementRef} on the available $user.id value.
	 *
	 * @return the user.id value
	 */
	static Value userId() {
		return CDS.QL.create.userId().type(String.class);
	}

	static CqnStar star() {
		return CqnStar.star();
	}

	/**
	 * Creates a {@link CqnListValue} composing given values
	 *
	 * @param values the components
	 * @return the list value
	 */
	static CqnListValue list(List values) {
		return CDS.QL.create.list(values);
	}

	/**
	 * Creates a {@link CqnListValue} composing given values
	 *
	 * @param values the items
	 * @return the list value
	 */
	static CqnListValue list(CqnValue... values) {
		return list(Arrays.asList(values));
	}

	/**
	 * Creates a predicate from a map of element names to values or parameters. The
	 * map entries are transformed into equality predicates and joined via
	 * and.
	 *
	 * @param elementToValueMap the element name to value map defining the condition
	 * @return the matching predicate
	 */
	static Predicate matching(Map elementToValueMap) {
		return CDS.QL.builder.matching(elementToValueMap);
	}

	/**
	 * Creates a {@link CqnSortSpecification} that sorts a value by a given order
	 *
	 * @param value the value
	 * @param order the order
	 * @return the sort specification
	 */
	static CqnSortSpecification sort(CqnValue value, Order order) {
		return CDS.QL.create.sort(value, order);
	}

	/**
	 * Creates a predicate that tests if this value matches a specified regular
	 * expression
	 *
	 * @param value   the value that is tested
	 * @param pattern Regular expression represented as a string value
	 * @param options Regular expression options represented as a string value
	 * @return the predicate to match the expression
	 */
	static Predicate matchesPattern(CqnValue value, CqnValue pattern, CqnValue options) {
		return CDS.QL.create.matchesPattern(value, pattern, options);
	}

	/**
	 * Creates a predicate that tests if this value matches a specified regular
	 * expression
	 *
	 * @param value   the value that is tested
	 * @param pattern Regular expression represented as a string value
	 * @return the predicate to match the expression
	 */
	static Predicate matchesPattern(CqnValue value, CqnValue pattern) {
		return CDS.QL.create.matchesPattern(value, pattern);
	}

	/**
	 * Creates a predicate that tests if this value matches a specified regular
	 * expression
	 *
	 * @param value   the value that is tested
	 * @param pattern Regular expression represented as a plain string
	 * @return the predicate to match the expression
	 */
	static Predicate matchesPattern(CqnValue value, String pattern) {
		return CDS.QL.create.matchesPattern(value, CQL.val(pattern));
	}

	/**
	 * Creates a predicate that tests if this value matches a specified regular
	 * expression
	 *
	 * @param value              the value that is tested
	 * @param pattern            Regular expression represented as a string value
	 * @param caseInsensitive    If true, the test is case-insensitive
	 * @param multiLineSensitive If true, the test is multi-line sensitive
	 * @return the predicate to match the expression
	 */
	static Predicate matchesPattern(CqnValue value, CqnValue pattern, boolean caseInsensitive,
			boolean multiLineSensitive) {
		return CDS.QL.create.matchesPattern(value, pattern, caseInsensitive, multiLineSensitive);
	}

	/**
	 * Starts a chain of when-then expressions.
	 * 
	 * @param pred the {@link CqnCaseExpression.Case#condition() condition} of the
	 *             first case.
	 * @return a builder to specify the case's return value
	 */
	static When when(CqnPredicate pred) {
		return CDS.QL.create.when(pred);
	}
	
	/**
	 * Creates a builder for a {@link CqnCaseExpression.Case case} 
	 * 
	 * @return a builder to connect more cases to
	 */
	static Then cases() {
		return CDS.QL.create;
	}

}