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

com.sap.cds.ql.impl.CqnBuilderImpl Maven / Gradle / Ivy

There is a newer version: 3.8.0
Show newest version
/************************************************************************
 * © 2019-2023 SAP SE or an SAP affiliate company. All rights reserved. *
 ************************************************************************/
package com.sap.cds.ql.impl;

import static com.sap.cds.impl.builder.model.ElementRefImpl.elementRef;
import static com.sap.cds.impl.builder.model.StructuredTypeImpl.structuredType;
import static com.sap.cds.impl.builder.model.StructuredTypeRefImpl.typeRef;

import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import com.sap.cds.impl.builder.model.ArithmeticExpr;
import com.sap.cds.impl.builder.model.BooleanFunctionCall;
import com.sap.cds.impl.builder.model.ComparisonPredicate;
import com.sap.cds.impl.builder.model.Conjunction;
import com.sap.cds.impl.builder.model.Connective;
import com.sap.cds.impl.builder.model.ContainmentTest;
import com.sap.cds.impl.builder.model.CqnParam;
import com.sap.cds.impl.builder.model.Disjunction;
import com.sap.cds.impl.builder.model.ElementRefBuilder;
import com.sap.cds.impl.builder.model.ElementRefImpl;
import com.sap.cds.impl.builder.model.ExistsSubquery;
import com.sap.cds.impl.builder.model.ExpandBuilder;
import com.sap.cds.impl.builder.model.ExpressionImpl;
import com.sap.cds.impl.builder.model.InPredicate;
import com.sap.cds.impl.builder.model.ListValue;
import com.sap.cds.impl.builder.model.LiteralImpl;
import com.sap.cds.impl.builder.model.MatchPredicate;
import com.sap.cds.impl.builder.model.Negation;
import com.sap.cds.impl.builder.model.ScalarFunctionCall;
import com.sap.cds.impl.builder.model.SearchPredicate;
import com.sap.cds.impl.builder.model.StructuredTypeProxy;
import com.sap.cds.impl.builder.model.StructuredTypeRefBuilder;
import com.sap.cds.impl.parser.builder.SortSpecificationImpl;
import com.sap.cds.impl.parser.token.CqnPlainImpl;
import com.sap.cds.impl.parser.token.RefSegmentImpl;
import com.sap.cds.ql.BooleanFunction;
import com.sap.cds.ql.CQL;
import com.sap.cds.ql.CqnBuilder;
import com.sap.cds.ql.CqnParser;
import com.sap.cds.ql.Delete;
import com.sap.cds.ql.ElementRef;
import com.sap.cds.ql.Expand;
import com.sap.cds.ql.FunctionCall;
import com.sap.cds.ql.Insert;
import com.sap.cds.ql.Literal;
import com.sap.cds.ql.Parameter;
import com.sap.cds.ql.Predicate;
import com.sap.cds.ql.RefBuilder;
import com.sap.cds.ql.RefSegment;
import com.sap.cds.ql.Select;
import com.sap.cds.ql.Source;
import com.sap.cds.ql.StructuredType;
import com.sap.cds.ql.StructuredTypeRef;
import com.sap.cds.ql.Update;
import com.sap.cds.ql.Upsert;
import com.sap.cds.ql.Value;
import com.sap.cds.ql.cqn.CqnArithmeticExpression;
import com.sap.cds.ql.cqn.CqnComparisonPredicate;
import com.sap.cds.ql.cqn.CqnConnectivePredicate.Operator;
import com.sap.cds.ql.cqn.CqnContainmentTest;
import com.sap.cds.ql.cqn.CqnElementRef;
import com.sap.cds.ql.cqn.CqnExpand;
import com.sap.cds.ql.cqn.CqnListValue;
import com.sap.cds.ql.cqn.CqnMatchPredicate.Quantifier;
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.CqnStatement;
import com.sap.cds.ql.cqn.CqnStructuredTypeRef;
import com.sap.cds.ql.cqn.CqnValue;
import com.sap.cds.ql.cqn.Modifier;
import com.sap.cds.reflect.CdsBaseType;
import com.sap.cds.reflect.CdsEntity;

public class CqnBuilderImpl implements CqnBuilder {

	private final CqnParserImpl parser = new CqnParserImpl();

	@Override
	public Select> select(CqnStructuredTypeRef ref) {
		return SelectBuilder.from(ref);
	}

	@Override
	public Insert insert(CqnStructuredTypeRef ref) {
		return XsertBuilder.insert(ref);
	}

	@Override
	public Upsert upsert(CqnStructuredTypeRef ref) {
		return XsertBuilder.upsert(ref);
	}

	@Override
	public Update> update(CqnStructuredTypeRef ref) {
		return UpdateBuilder.entity(ref);
	}

	@Override
	public Delete> delete(CqnStructuredTypeRef ref) {
		return DeleteBuilder.from(ref);
	}

	@Override
	public > Select select(Source source) {
		return SelectBuilder.from(source);
	}

	@Override
	public Select> select(String entityName) {
		return SelectBuilder.from(entityName);
	}

	@Override
	public Select> select(String entityName, UnaryOperator> path) {
		return SelectBuilder.from(entityName, path);
	}

	@Override
	public Insert insert(String entityName, UnaryOperator> path) {
		CqnStructuredTypeRef structType = applyPath(entityName, path);
		return XsertBuilder.insert(structType);
	}

	@Override
	public Upsert upsert(String entityName, UnaryOperator> path) {
		CqnStructuredTypeRef structType = applyPath(entityName, path);
		return XsertBuilder.upsert(structType);
	}

	@Override
	public Update> update(String entityName, UnaryOperator> path) {
		CqnStructuredTypeRef structType = applyPath(entityName, path);
		return UpdateBuilder.entity(structType);
	}

	@Override
	public Update> update(CdsEntity entity, UnaryOperator> path) {
		return update(entity.getQualifiedName(), path);
	}

	@Override
	public Delete> delete(String entityName, UnaryOperator> path) {
		StructuredTypeRef structType = applyPath(entityName, path);
		return DeleteBuilder.from(structType);
	}

	private static StructuredTypeRef applyPath(String entityName, UnaryOperator> path) {
		StructuredType root = structuredType(entityName);

		return typeRef(path.apply(root));
	}

	@Override
	public > Select select(Class entity) {
		return select((Source) StructuredTypeProxy.create(entity));
	}

	@Override
	public , R extends StructuredType> Select select(Class entity,
			Function path) {
		return select((Source) path.apply(StructuredTypeProxy.create(entity)));
	}

	@Override
	public Select> select(CqnSelect select) {
		return SelectBuilder.from(select);
	}

	@Override
	public , R extends StructuredType> Insert insert(Class entity,
			Function path) {
		return XsertBuilder.insert(path.apply(StructuredTypeProxy.create(entity)));
	}

	@Override
	public , R extends StructuredType> Upsert upsert(Class entity,
			Function path) {
		return XsertBuilder.upsert(path.apply(StructuredTypeProxy.create(entity)));
	}

	@Override
	public , R extends StructuredType> Update update(Class entity,
			Function path) {
		return UpdateBuilder.entity(path.apply(StructuredTypeProxy.create(entity)));
	}

	@Override
	public , R extends StructuredType> Delete delete(Class entity,
			Function path) {
		return DeleteBuilder.from(path.apply(StructuredTypeProxy.create(entity)));
	}

	@Override
	public Select> select(CdsEntity entity) {
		return select(entity.getQualifiedName());
	}

	@Override
	public Select> select(CdsEntity entity, UnaryOperator> path) {
		return select(entity.getQualifiedName(), path);
	}

	@Override
	public Insert insert(CdsEntity entity, UnaryOperator> path) {
		return insert(entity.getQualifiedName(), path);
	}

	@Override
	public Upsert upsert(CdsEntity entity, UnaryOperator> path) {
		return upsert(entity.getQualifiedName(), path);
	}

	@Override
	public Delete> delete(CdsEntity entity, UnaryOperator> path) {
		return delete(entity.getQualifiedName(), path);
	}

	@Override
	public > Delete delete(E entity) {
		return DeleteBuilder.from(entity);
	}

	@Override
	public > Insert insert(E entity) {
		return XsertBuilder.insert(entity);
	}

	@Override
	public > Upsert upsert(E entity) {
		return XsertBuilder.upsert(entity);
	}

	@Override
	public > Update update(E entity) {
		return UpdateBuilder.entity(entity);
	}

	@Override
	public  R copy(S statement) {
		return copy(statement, ExpressionVisitor.COPY);
	}

	@Override
	@SuppressWarnings("unchecked")
	public  R copy(S statement, Modifier modifier) {
		if (statement.isSelect()) {
			return (R) SelectBuilder.copy(statement.asSelect(), modifier);
		}
		if (statement.isInsert()) {
			return (R) XsertBuilder.copy(statement.asInsert(), modifier);
		}
		if (statement.isUpsert()) {
			return (R) XsertBuilder.copy(statement.asUpsert(), modifier);
		}
		if (statement.isUpdate()) {
			return (R) UpdateBuilder.copy(statement.asUpdate(), modifier);
		}
		if (statement.isDelete()) {
			return (R) DeleteBuilder.copy(statement.asDelete(), modifier);
		}
		throw new UnsupportedOperationException("Cannot copy statement " + statement);
	}

	@Override
	public RefBuilder copy(CqnStructuredTypeRef ref) {
		return StructuredTypeRefBuilder.copy(ref);
	}

	@Override
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public RefBuilder> copy(CqnElementRef ref) {
		return (RefBuilder) ElementRefBuilder.copy(ref);
	}

	@Override
	public Expand copy(CqnExpand expand) {
		CqnStructuredTypeRef ref = CQL.copy(expand.ref()).build();
		Expand copy = CQL.to(ref.segments()).as(ref.alias().orElse(null)).expand(expand.items())
				.orderBy(expand.orderBy()).limit(expand.top(), expand.skip());
		if (((ExpandBuilder) expand).lazy()) {
			((ExpandBuilder) copy).lazy(true);
		}
		return copy;
	}

	@Override
	public Predicate copy(CqnPredicate pred) {
		return ExpressionVisitor.copy(pred);
	}

	@Override
	public Predicate copy(CqnPredicate pred, Modifier modifier) {
		return ExpressionVisitor.copy(pred, modifier);
	}

	@Override
	public CqnParser parse() {
		return parser;
	}

	@Override
	public QueryBuilderSupport support() {
		return new QueryBuilderSupport() {
			@Override
			public  Parameter param() {
				return CqnParam.param();
			}

			@Override
			public  Parameter param(String name) {
				return CqnParam.param(name);
			}

			@Override
			public  FunctionCall func(String functionName, Iterable args) {
				return ScalarFunctionCall.create(functionName, args);
			}

			@Override
			public BooleanFunction booleanFunc(String functionName, List args) {
				return BooleanFunctionCall.create(functionName, args);
			}

			@Override
			public CqnListValue list(List values) {
				return ListValue.of(values);
			}

			@Override
			public  Literal literal(T val) {
				return LiteralImpl.val(val);
			}

			@Override
			public  Literal constant(T value) {
				return LiteralImpl.constant(value);
			}

			@Override
			public  Literal val(T value) {
				return LiteralImpl.val(value);
			}

			@Override
			public Value plain(String val) {
				return CqnPlainImpl.plain(val);
			}

			@Override
			public Predicate not(CqnPredicate p) {
				return Negation.not(p);
			}

			@Override
			public Predicate connect(Operator operator, Iterable predicates) {
				return Connective.create(operator, predicates);
			}

			@Override
			public Value toLower(Value val) {
				return ScalarFunctionCall.create("tolower", val).type(CdsBaseType.STRING);
			}

			@Override
			public Value toUpper(Value val) {
				return ScalarFunctionCall.create("toupper", val).type(CdsBaseType.STRING);
			}

			@Override
			public StructuredType entity(String qualifiedName) {
				return structuredType(qualifiedName);
			}

			@Override
			public  ElementRef get(String path) {
				return ElementRefImpl.parse(path);
			}

			@Override
			public  ElementRef get(List segments) {
				return elementRef(segments);
			}

			@Override
			public StructuredType to(String path) {
				return structuredType(typeRef(path.split("\\.")));
			}

			@Override
			public StructuredType to(List segments) {
				return structuredType(typeRef(segments));
			}

			@Override
			public RefSegment refSegment(String id) {
				return RefSegmentImpl.refSegment(id);
			}

			@Override
			public Segment refSegment(String id, CqnPredicate filter) {
				return RefSegmentImpl.refSegment(id, filter);
			}

			@Override
			public List refSegments(List segmentIds) {
				return segmentIds.stream().map(this::refSegment).collect(Collectors.toList());
			}

			@Override
			public Value expression(CqnValue left, CqnArithmeticExpression.Operator op, CqnValue right) {
				return ArithmeticExpr.expression(left, op, right);
			}

			@Override
			public Predicate comparison(CqnValue lhs, CqnComparisonPredicate.Operator op, CqnValue rhs) {
				return ComparisonPredicate.pred(lhs, op, rhs);
			}

			@Override
			public Predicate in(CqnValue lhs, Collection values) {
				return InPredicate.in(lhs, values.stream());
			}

			@Override
			public Predicate in(CqnValue lhs, CqnValue valueSet) {
				return InPredicate.in(lhs, valueSet);
			}

			@Override
			public Predicate search(String term) {
				return new SearchPredicate(term);
			}

			@Override
			public Predicate exists(CqnSelect subQuery) {
				return new ExistsSubquery(subQuery);
			}

			@Override
			public Predicate match(CqnStructuredTypeRef ref, CqnPredicate pred, Quantifier quantifier) {
				return MatchPredicate.match(ref, quantifier, pred);
			}

			public Value now() {
				return get("$now");
			}

			@Override
			public Value validFrom() {
				return elementRef("$at", "from");
			}

			@Override
			public Value validTo() {
				return elementRef("$at", "to");
			}

			@Override
			public Value userLocale() {
				return elementRef("$user", "locale");
			}

			@Override
			public Value userId() {
				return elementRef("$user", "id");
			}

			@Override
			public Value countDistinct(CqnValue value) {
				return ScalarFunctionCall.create("countDistinct", value);
			}

			@Override
			public Predicate containment(CqnContainmentTest.Position position, CqnValue value, CqnValue term,
					boolean caseInsensitive) {
				return ContainmentTest.create(position, value, term, caseInsensitive);
			}

			@Override
			public CqnSortSpecification sort(CqnValue value, Order order) {
				return SortSpecificationImpl.sort(value, order);
			}

			@Override
			public Collector withOr() {
				return Disjunction.or();
			}

			@Override
			public Collector withAnd() {
				return Conjunction.and();
			}
		};
	}

	public Predicate matching(Map keyValueMap) {
		return ExpressionImpl.matching(keyValueMap);
	}
}