![JAR search and dependency download from the Maven repository](/logo.png)
com.bigdata.rdf.sparql.ast.FunctionNode Maven / Gradle / Ivy
package com.bigdata.rdf.sparql.ast;
import java.io.Serializable;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import org.openrdf.model.URI;
import com.bigdata.bop.BOp;
import com.bigdata.bop.IValueExpression;
import com.bigdata.bop.NV;
/**
* AST node for anything which is neither a constant nor a variable, including
* math operators, string functions, etc. The {@link FunctionNode} arguments are
* the ordered list {@link ValueExpressionNode}s that are the arguments to the
* SPARQL function.
*
* @author Mike Personick
* @version $Id$
*/
public class FunctionNode extends ValueExpressionNode {
/**
*
*/
private static final long serialVersionUID = 1L;
interface Annotations extends ValueExpressionNode.Annotations {
/**
* The function URI from the {@link FunctionRegistry}.
*/
String FUNCTION_URI = FunctionNode.class.getName() + ".functionURI";
/**
* The scalar values needed to construct the {@link IValueExpression}.
* This is a {@link Serializable} {@link Map} with {@link String} keys
* and {@link Object} values.
*/
String SCALAR_VALS = FunctionNode.class.getName() + ".scalarVals";
}
/**
* Construct a function node in the AST.
*
* @param functionURI
* the function URI. see {@link FunctionRegistry}
* @param scalarValues
* One or more scalar values that are passed to the function
* @param args
* the arguments to the function.
*
* @see
* Occasional error on BSBM Explore query
*/
public FunctionNode(//
final URI functionURI,
final Map scalarValues,
final ValueExpressionNode... args) {
super(args, NV.asMap(new NV[] {
new NV(Annotations.SCALAR_VALS, scalarValues),
new NV(Annotations.FUNCTION_URI, functionURI), }));
if (functionURI == null)
throw new IllegalArgumentException();
// scalarValues MAY be null.
// super(args, null/*anns*/);
//
// super.setProperty(Annotations.SCALAR_VALS, scalarValues);
//
// super.setProperty(Annotations.FUNCTION_URI, functionURI);
}
/**
* Constructor required for {@link com.bigdata.bop.BOpUtility#deepCopy(FilterNode)}.
*/
public FunctionNode(final FunctionNode op) {
super(op);
}
/**
* Required shallow copy constructor.
*/
public FunctionNode(final BOp[] args, final Map anns) {
super(args, anns);
}
public URI getFunctionURI() {
return (URI) getRequiredProperty(Annotations.FUNCTION_URI);
}
/**
* Returns an unmodifiable map because if the scalar values are modified, we
* need to clear the value expression cache. This is handled correctly by
* {@link #setScalarValues(Map)}.
*/
public Map getScalarValues() {
@SuppressWarnings("unchecked")
final Map scalarValues = (Map) getProperty(Annotations.SCALAR_VALS);
if (scalarValues == null) {
return Collections.emptyMap();
}
return Collections.unmodifiableMap(scalarValues);
}
/**
* Overridden to clear the cached value expression.
*/
@Override
public void invalidate() {
super.clearProperty(Annotations.VALUE_EXPR);
super.invalidate();
}
/**
* Return true
iff the {@link FunctionNode} makes use of a
* {@link FunctionRegistry#BOUND} operator.
*
* @return true
iff it uses BOUND()
*
* TODO Unit test.
*/
public boolean isBound() {
if (FunctionRegistry.BOUND.equals(getFunctionURI()))
return true;
final int arity = arity();
for (int i = 0; i < arity; i++) {
final BOp child = get(i);
if (child instanceof FunctionNode) {
if (!((FunctionNode) child).isBound()) {
return true;
}
}
}
return false;
}
/*
* Factory methods.
*/
/**
* Return t1 AND t2
.
*/
static public FunctionNode AND(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.AND, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 OR t2
.
*/
static public FunctionNode OR(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.OR, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 OR t2
.
*/
static public FunctionNode NOT(final ValueExpressionNode inner) {
return new FunctionNode(FunctionRegistry.NOT, null/* scalarValues */,
new ValueExpressionNode[] { inner });
}
/**
* Return t1 + t2
(aka ADD).
*/
static public FunctionNode add(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.ADD, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 - t2
(aka SUBTRACT).
*/
static public FunctionNode subtract(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.SUBTRACT, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return sameTerm(t1,t2)
(aka EQ).
*/
static public FunctionNode sameTerm(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.SAME_TERM, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 = t2
(aka EQ aka RDFTERM-EQUALS).
*/
static public FunctionNode EQ(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.EQ, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 != t2
*/
static public FunctionNode NE(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.NE, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 < t2
*/
static public FunctionNode LT(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.LT, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 > t2
*/
static public FunctionNode GT(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.GT, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 <= t2
*/
static public FunctionNode LE(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.LE, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return t1 >= t2
*/
static public FunctionNode GE(final ValueExpressionNode t1,
final ValueExpressionNode t2) {
return new FunctionNode(FunctionRegistry.GE, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Return min(v1,v2)
*/
static public FunctionNode MIN(
final ValueExpressionNode v1, final ValueExpressionNode v2) {
return new FunctionNode(FunctionRegistry.MIN, null/* scalarValues */,
new ValueExpressionNode[] { v1, v2 });
}
/**
* Return max(v1,v2)
*/
static public FunctionNode MAX(
final ValueExpressionNode v1, final ValueExpressionNode v2) {
return new FunctionNode(FunctionRegistry.MAX, null/* scalarValues */,
new ValueExpressionNode[] { v1, v2 });
}
/**
* Return a binary function op(t1,t2)
*/
static public FunctionNode binary(final URI uri, final TermNode t1,
final TermNode t2) {
return new FunctionNode(uri, null/* scalarValues */,
new ValueExpressionNode[] { t1, t2 });
}
/**
* Provides a pretty print representation with recursive descent.
*/
@Override
public String toString(int i) {
final StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
final Integer bopId = (Integer) getProperty(Annotations.BOP_ID);
if (bopId != null) {
sb.append("[" + bopId + "]");
}
sb.append("(");
int nwritten = 0;
final Iterator itr = argIterator();
while(itr.hasNext()) {
final BOp t = itr.next();
if (nwritten > 0)
sb.append(',');
if (t == null) {
sb.append("");
} else {
sb.append(((IValueExpressionNode)t).toString(i+1));
}
nwritten++;
}
sb.append(")");
annotationsToString(sb, i);
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy