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

com.bigdata.rdf.internal.constraints.ConditionalBind Maven / Gradle / Ivy

package com.bigdata.rdf.internal.constraints;

import java.util.Map;

import com.bigdata.bop.BOp;
import com.bigdata.bop.Constant;
import com.bigdata.bop.IBind;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IValueExpression;
import com.bigdata.bop.IVariable;
import com.bigdata.bop.ImmutableBOp;
import com.bigdata.bop.NV;
import com.bigdata.rdf.error.SparqlTypeErrorException;
import com.bigdata.rdf.internal.IV;

/**
 * Operator causes a variable to be bound to the result of its evaluation as a
 * side-effect unless the variable is already bound and the as-bound value does
 * not compare as equals.
 * 

* Note: This is intended for use within a {@link BindingConstraint}. That * * @author mroycsi */ public class ConditionalBind extends ImmutableBOp implements IValueExpression, IBind, IPassesMaterialization { private static final long serialVersionUID = 1L; public interface Annotations extends BOp.Annotations { String PROJECTION = ConditionalBind.class.getName() + ".projection"; } protected transient Boolean projection; /** * Constructor required for {@link com.bigdata.bop.BOpUtility#deepCopy(FilterNode)}. */ public ConditionalBind(ConditionalBind op) { super(op); } /** * @param var * The {@link IVariable} which will be bound to the result of * evaluating the associated value expression. * @param expr * The {@link IValueExpression} to be evaluated. */ public ConditionalBind(IVariable var, IValueExpression expr,boolean projection) { this(new BOp[] { var, expr }, NV.asMap(new NV(Annotations.PROJECTION, projection))); this.projection = projection; } /** * Required shallow copy constructor. * * @param args * @param annotations */ public ConditionalBind(BOp[] args, Map annotations) { super(args, annotations); if (getProperty(Annotations.PROJECTION) == null) throw new IllegalArgumentException(); } boolean isProjection(){ if (projection == null) { projection = (Boolean) getRequiredProperty(Annotations.PROJECTION); } return projection; } /** * Return the variable which will be bound to the result of evaluating the * associated value expression. */ @SuppressWarnings("unchecked") public IVariable getVar() { return (IVariable) get(0); } /** * Return the value expression. */ @SuppressWarnings("unchecked") public IValueExpression getExpr() { return (IValueExpression) get(1); } public E get(final IBindingSet bindingSet) { final IVariable var = getVar(); final IValueExpression expr = getExpr(); /* * This code has been removed since (per LeeF) an aggregate in a * non-aggregate context should be an error. */ // /* // * Evaluate the value expression. // * // * Note: This also handles the special case of an aggregate appearing // * within a function call context outside of a projection. // */ // final E val; // final boolean aggregate = !isProjection() // && (expr instanceof IAggregate); // if (aggregate) { // ((IAggregate) expr).reset(); // expr.get(bindingSet); // val = (E) ((IAggregate) expr).done(); // } else { // val = expr.get(bindingSet); // } final E val = expr.get(bindingSet); // evaluate the value expression. final E existing = var.get(bindingSet); // lookup current bound value. try{ if( val == null){ throw new SparqlTypeErrorException.UnboundVarException(); } if (existing == null) { // bind the variable as a side-effect. bindingSet.set(var, new Constant(val)); // return the evaluated value return val; } else { /* * Note: A BindingConstraint wrapping the ConditionalBind will see * the [null] and fail the solution. This avoids throwing the * SPARQLTypeErrorException, which has more overhead. */ return (val.equals(existing)) ? val : null; } }catch(SparqlTypeErrorException typeError){ /* * Note: If an assignment fails to evaluate, and there is already a binding in * the solution with the same variable name, the solution fails. * If there is not already an assignment, rethrow the exception, so that the * BindingConstraint can pass the solution, since the sparql spec says a * failure in an assignment passes the solution. */ if(existing!=null){ return null; }else{ throw typeError; } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy