Expressions.java
/*******************************************************************************
* Copyright (c) 2018 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sparqlbuilder.constraint;
import static org.eclipse.rdf4j.sparqlbuilder.constraint.SparqlFunction.ABS;
import static org.eclipse.rdf4j.sparqlbuilder.constraint.SparqlFunction.BNODE;
import static org.eclipse.rdf4j.sparqlbuilder.constraint.SparqlFunction.BOUND;
import static org.eclipse.rdf4j.sparqlbuilder.constraint.SparqlFunction.CEIL;
import static org.eclipse.rdf4j.sparqlbuilder.constraint.SparqlFunction.COALESCE;
import static org.eclipse.rdf4j.sparqlbuilder.constraint.SparqlFunction.CONCAT;
import static org.eclipse.rdf4j.sparqlbuilder.constraint.SparqlFunction.REGEX;
import static org.eclipse.rdf4j.sparqlbuilder.rdf.Rdf.iri;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.sparqlbuilder.core.Assignable;
import org.eclipse.rdf4j.sparqlbuilder.core.Variable;
import org.eclipse.rdf4j.sparqlbuilder.rdf.Iri;
import org.eclipse.rdf4j.sparqlbuilder.rdf.Rdf;
import org.eclipse.rdf4j.sparqlbuilder.rdf.RdfLiteral;
import org.eclipse.rdf4j.sparqlbuilder.rdf.RdfValue;
/**
* A class with static methods to create SPARQL expressions. Obviously there's some more flushing out TODO still
*
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#SparqlOps"> SPARQL Function Definitions</a>
*/
public class Expressions {
private Expressions() {
}
/**
* <code>ABS(operand</code>)
*
* @param operand the argument to the absolute value function
* @return an ABS() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-abs"> SPARQL ABS Function</a>
*/
public static Expression<?> abs(Number operand) {
return abs(Rdf.literalOf(operand));
}
/**
* <code>ABS(operand</code>)
*
* @param operand the argument to the absolute value function
* @return an ABS() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-abs"> SPARQL ABS Function</a>
*/
public static Expression<?> abs(Operand operand) {
return function(ABS, operand);
}
/**
* <code>BNODE()</code>
*
* @return a no-arg BNODE() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-bnode"> SPARQL BNODE Function</a>
*/
public static Expression<?> bnode() {
return function(BNODE);
}
/**
* <code>BNODE(operand)</code>
*
* @param literal the RDF literal argument to the function
* @return a BNODE() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-bnode"> SPARQL BNODE Function</a>
*/
public static Expression<?> bnode(RdfLiteral<?> literal) {
return function(BNODE, literal);
}
/**
* <code>BNODE(operand)</code>
*
* @param literal the String literal argument to the function
* @return a BNODE() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-bnode"> SPARQL BNODE Function</a>
*/
public static Expression<?> bnode(String literal) {
return function(BNODE, Rdf.literalOf(literal));
}
/**
* <code>BOUND(operand)</code>
*
* @param var the SPARQL variable argument to the function
* @return a BOUND() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-bound"> SPARQL BOUND Function</a>
*/
public static Expression<?> bound(Variable var) {
return function(BOUND, var);
}
/**
* <code>CEIL(operand)</code>
*
* @param operand the argument to the function
* @return a CEIL() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-ceil"> SPARQL CEIL Function</a>
*/
public static Expression<?> ceil(Operand operand) {
return function(CEIL, operand);
}
/**
* <code>COALESCE(operand1, operand2, ... , operandN)</code>
*
* @param operands the arguments to the function
* @return a COALESCE() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-coalesce"> SPARQL COALESCE Function</a>
*/
public static Expression<?> coalesce(Operand... operands) {
return function(COALESCE, operands);
}
/**
* <code>CONCAT(operand1, operand2, ... , operandN)</code>
*
* @param operands the arguments to the function
* @return a CONCAT() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-concat"> SPARQL CONCAT Function</a>
*/
public static Expression<?> concat(Operand... operands) {
return function(CONCAT, operands);
}
/**
* <code>REGEX(testString, pattern)<code>
*
* @param testString the text to match against
* @param pattern the regex pattern to match
* @return a REGEX() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-regex"> SPARQL REGEX Function</a>
*/
public static Expression<?> regex(Operand testString, String pattern) {
return regex(testString, Rdf.literalOf(pattern));
}
/**
* <code>REGEX(testString, pattern, flags)<code>
*
* @param testString the text to match against
* @param pattern the regular expression pattern to match
* @param flags flags to specify matching options
* @return a REGEX() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-regex"> SPARQL REGEX Function</a>
*/
public static Expression<?> regex(Operand testString, String pattern, String flags) {
return regex(testString, Rdf.literalOf(pattern), Rdf.literalOf(flags));
}
/**
* <code>REGEX(testString, pattern)<code>
*
* @param testString the text to match against
* @param pattern the regex pattern to match
* @return a REGEX() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-regex"> SPARQL REGEX Function</a>
*/
public static Expression<?> regex(Operand testString, Operand pattern) {
return function(REGEX, testString, pattern);
}
/**
* <code>REGEX(testString, pattern, flags)<code>
*
* @param testString the text to match against
* @param pattern the regular expression pattern to match
* @param flags flags to specify matching options
* @return a REGEX() function
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-regex"> SPARQL REGEX Function</a>
*/
public static Expression<?> regex(Operand testString, Operand pattern, Operand flags) {
return function(REGEX, testString, pattern, flags);
}
/**
* {@code STR(literal)} or {@code STR(iri)}
*
* @param operand the arg to convert to a string
* @return a {@code STR()} function
* @see <a href="https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#func-str"> SPARQL STR Function</a>
*/
public static Expression<?> str(Operand operand) {
return function(SparqlFunction.STRING, operand);
}
public static Expression<?> custom(Iri functionIri, Operand... operands) {
return new CustomFunction(functionIri).addOperand(operands);
}
public static Expression<?> custom(IRI functionIri, Operand... operands) {
return new CustomFunction(functionIri).addOperand(operands);
}
/**
* {@code operand IN (expression1, expression2...)}
*
* @param searchTerm
* @param expressions
* @return an {@code IN} function
* @see <a href="https://www.w3.org/TR/sparql11-query/#func-in">SPARQL IN Function</a>
*/
public static Expression<?> in(Operand searchTerm, Operand... expressions) {
return new In(searchTerm, expressions);
}
/**
* {@code operand NOT IN (expression1, expression2...)}
*
* @param searchTerm
* @param expressions
* @return an {@code NOT IN} function
* @see <a href="https://www.w3.org/TR/sparql11-query/#func-not-in">SPARQL NOT IN Function</a>
*/
public static Expression<?> notIn(Operand searchTerm, Operand... expressions) {
return new In(searchTerm, false, expressions);
}
// ... etc...
/**
* Too lazy at the moment. Make the rest of the functions this way for now.
*
* @param function a SPARQL Function
* @param operands arguments to the function
* @return a function object of the given <code>function</code> type and <code>operands</code>
*/
public static Expression<?> function(SparqlFunction function, Operand... operands) {
return new Function(function).addOperand(operands);
}
/**
* <code>!operand</code>
*
* @param operand argument to the function
* @return logical not operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> not(Operand operand) {
return unaryExpression(UnaryOperator.NOT, operand);
}
/**
* <code>+operand</code>
*
* @param operand argument to the function
* @return unary plus operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> plus(Operand operand) {
return unaryExpression(UnaryOperator.UNARY_PLUS, operand);
}
/**
* <code>-operand</code>
*
* @param operand argument to the function
* @return unary minus operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> minus(Operand operand) {
return unaryExpression(UnaryOperator.UNARY_MINUS, operand);
}
private static UnaryOperation unaryExpression(UnaryOperator operator, Operand operand) {
return new UnaryOperation(operator).addOperand(operand);
}
/**
* <code>left = right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical equals operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> equals(Operand left, Operand right) {
return binaryExpression(BinaryOperator.EQUALS, left, right);
}
/**
* <code>left != right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical not equals operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> notEquals(Operand left, Operand right) {
return binaryExpression(BinaryOperator.NOT_EQUALS, left, right);
}
public static Expression<?> notEquals(Variable left, RdfValue right) {
return binaryExpression(BinaryOperator.NOT_EQUALS, left, right);
}
public static Expression<?> notEquals(Variable left, IRI right) {
return binaryExpression(BinaryOperator.NOT_EQUALS, left, iri(right));
}
/**
* <code>left > right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical greater than operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> gt(Number left, Number right) {
return binaryExpression(BinaryOperator.GREATER_THAN, Rdf.literalOf(left), Rdf.literalOf(right));
}
/**
* <code>left > right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical greater than operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> gt(Number left, Operand right) {
return binaryExpression(BinaryOperator.GREATER_THAN, Rdf.literalOf(left), right);
}
/**
* <code>left > right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical greater than operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> gt(Operand left, Number right) {
return binaryExpression(BinaryOperator.GREATER_THAN, left, Rdf.literalOf(right));
}
/**
* <code>left > right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical greater than operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> gt(Operand left, Operand right) {
return binaryExpression(BinaryOperator.GREATER_THAN, left, right);
}
/**
* <code>left >= right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical greater than or equals operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> gte(Operand left, Operand right) {
return binaryExpression(BinaryOperator.GREATER_THAN_EQUALS, left, right);
}
/**
* <code>left < right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical less than operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> lt(Number left, Number right) {
return binaryExpression(BinaryOperator.LESS_THAN, Rdf.literalOf(left), Rdf.literalOf(right));
}
/**
* <code>left < right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical less than operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> lt(Number left, Operand right) {
return binaryExpression(BinaryOperator.LESS_THAN, Rdf.literalOf(left), right);
}
/**
* <code>left < right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical less than operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> lt(Operand left, Number right) {
return binaryExpression(BinaryOperator.LESS_THAN, left, Rdf.literalOf(right));
}
/**
* <code>left < right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical less than operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> lt(Operand left, Operand right) {
return binaryExpression(BinaryOperator.LESS_THAN, left, right);
}
/**
* <code>left <= right</code>
*
* @param left the left operand
* @param right the right operand
* @return logical less than or equals operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> lte(Operand left, Operand right) {
return binaryExpression(BinaryOperator.LESS_THAN_EQUALS, left, right);
}
private static BinaryOperation binaryExpression(BinaryOperator operator, Operand op1, Operand op2) {
BinaryOperation op = new BinaryOperation(operator);
op.addOperand(op1).addOperand(op2);
return op;
}
/**
* <code>operand1 && operand2 && ... operandN</code>
*
* @param operands the arguments
* @return logical and operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> and(Operand... operands) {
return connectiveExpression(ConnectiveOperator.AND, operands);
}
/**
* <code>operand1 || operand2 || ... || operandN</code>
*
* @param operands the arguments
* @return logical or operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> or(Operand... operands) {
return connectiveExpression(ConnectiveOperator.OR, operands);
}
/**
* <code>operand1 + operand2 + ... + operandN</code>
*
* @param operands the arguments
* @return arithmetic addition operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> add(Operand... operands) {
return connectiveExpression(ConnectiveOperator.ADD, operands);
}
/**
* <code>operand1 - operand2 - ... - operandN</code>
*
* @param operands the arguments
* @return arithmetic subtraction operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> subtract(Operand... operands) {
return connectiveExpression(ConnectiveOperator.SUBTRACT, operands);
}
/**
* <code>operand1 * operand2 * ... * operandN</code>
*
* @param operands the arguments
* @return arithmetic multiplication operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> multiply(Operand... operands) {
return connectiveExpression(ConnectiveOperator.MULTIPLY, operands);
}
/**
* <code>operand1 / operand2 / ... / operandN</code>
*
* @param operands the arguments
* @return arithmetic division operation
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#OperatorMapping">SPARQL Operators</a>
*/
public static Expression<?> divide(Operand... operands) {
return connectiveExpression(ConnectiveOperator.DIVIDE, operands);
}
private static ConnectiveOperation connectiveExpression(ConnectiveOperator operator, Operand... operands) {
ConnectiveOperation op = new ConnectiveOperation(operator);
for (Operand operand : operands) {
op.addOperand(operand);
}
return op;
}
/**
* Aggregates
*/
/**
* {@code avg(...)}
*
* @param operand the expression to average
* @return an avg aggregate function
* @see <a href="https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#aggregates"> SPARQL aggregates</a>
*/
public static Aggregate avg(Operand operand) {
return new Aggregate(SparqlAggregate.AVG).addOperand(operand);
}
/**
* {@code count()}
*
* @param operand the expression to count
* @return a count aggregate
* @see <a href="https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#aggregates"> SPARQL aggregates</a>
*/
public static Aggregate count(Operand operand) {
return new Aggregate(SparqlAggregate.COUNT).addOperand(operand);
}
public static Aggregate countAll() {
return new Aggregate(SparqlAggregate.COUNT).countAll();
}
public static Aggregate group_concat(Operand... operands) {
return new Aggregate(SparqlAggregate.GROUP_CONCAT).addOperand(operands);
}
public static Aggregate group_concat(String separator, Operand... operands) {
return new Aggregate(SparqlAggregate.GROUP_CONCAT).addOperand(operands).separator(separator);
}
public static Aggregate max(Operand operand) {
return new Aggregate(SparqlAggregate.MAX).addOperand(operand);
}
public static Aggregate min(Operand operand) {
return new Aggregate(SparqlAggregate.MIN).addOperand(operand);
}
public static Aggregate sample(Operand operand) {
return new Aggregate(SparqlAggregate.SAMPLE).addOperand(operand);
}
public static Aggregate sum(Operand operand) {
return new Aggregate(SparqlAggregate.SUM).addOperand(operand);
}
public static Bind bind(Assignable exp, Variable var) {
return new Bind(exp, var);
}
public static Expression<?> notIn(Variable var, RdfValue... options) {
return new NotIn(var, options);
}
public static Expression<?> notIn(Variable var, IRI... options) {
return notIn(var, parseIRIOptionsToRDFValueVarargs(options));
}
public static Expression<?> in(Variable var, RdfValue... options) {
return new In(var, options);
}
public static Expression<?> in(Variable var, IRI... options) {
return in(var, parseIRIOptionsToRDFValueVarargs(options));
}
public static Expression<?> strdt(Operand lexicalForm, Operand datatype) {
return function(SparqlFunction.STRDT, lexicalForm, datatype);
}
public static Expression<?> strlen(Operand operand) {
return function(SparqlFunction.STRLEN, operand);
}
public static Expression<?> isBlank(Variable var) {
return function(SparqlFunction.IS_BLANK, var);
}
public static Expression<?> datatype(Variable var) {
return function(SparqlFunction.DATATYPE, var);
}
public static Expression<?> iff(Operand testExp, Operand thenExp, Operand elseExp) {
return function(SparqlFunction.IF, testExp, thenExp, elseExp);
}
/**
* Parses IRI... options to RdfValue... options to give more flexibility in expressions use
*
* @param options options as IRIs
* @return options as RDFValues
*/
private static RdfValue[] parseIRIOptionsToRDFValueVarargs(IRI... options) {
List<RdfValue> rdfValueOptions = new ArrayList<>();
for (IRI option : options) {
rdfValueOptions.add(iri(option));
}
return rdfValueOptions.toArray(new RdfValue[0]);
}
}