
com.weaverplatform.sp4rql.model.solution.Sp4rqlSolution Maven / Gradle / Ivy
package com.weaverplatform.sp4rql.model.solution;
import com.weaverplatform.sp4rql.error.ParseException;
import com.weaverplatform.sp4rql.model.expression.ExpressionArgument;
import com.weaverplatform.sp4rql.model.expression.ExpressionUnit;
import com.weaverplatform.sp4rql.model.expression.OperatorType;
import com.weaverplatform.sp4rql.model.restriction.*;
import com.weaverplatform.sp4rql.model.scope.ScopeSimple;
import com.weaverplatform.sp4rql.model.scope.Sp4rqlScope;
import com.weaverplatform.sp4rql.model.token.*;
import com.weaverplatform.util.IndentStringBuilder;
import java.util.HashSet;
/*
* A solution is a set of elements that needs to be resolved during query execution.
* Typically the solution will be bound to a ?variable in the result set. But also
* non returned solution are used.
*
* The type of elements inside the selection can be derived from the query.
*/
public class Sp4rqlSolution {
protected VariableToken binding;
protected ExpressionUnit aggregationExpression = null;
protected HashSet restrictions = new HashSet<>();
protected final SolutionType type = new SolutionType();
protected HashSet equalSolutions = new HashSet<>();
protected Sp4rqlScope scope;
public Sp4rqlSolution(VariableToken token) {
binding = token;
}
public void setScope(Sp4rqlScope scope) {
this.scope = scope;
}
private void addEqualSolution(Sp4rqlSolution other) {
this.equalSolutions.add(other);
other.equalSolutions.add(this);
}
public void addRestriction(Sp4rqlRestriction restriction) {
restrictions.add(restriction);
}
public void setAggregationExpression(ExpressionUnit expression) {
this.aggregationExpression = expression;
}
public VariableToken getBinding() {
return binding;
}
public HashSet getRestrictions() {
return restrictions;
}
public void analyseTypes() {
if(aggregationExpression != null) {
analyseTypes(aggregationExpression);
} else {
for (Sp4rqlRestriction restriction : getRestrictions()) {
if (restriction instanceof BindRestriction) {
analyseTypes((BindRestriction) restriction);
} else if (restriction instanceof FilterRestriction) {
// a filter restriction does not expose anything to a binding (todo: also check on type of input variables)
} else if (restriction instanceof SingleTermRestriction) {
analyseTypes((SingleTermRestriction) restriction);
} else if (restriction instanceof QuadRestriction) {
analyseTypes((QuadRestriction) restriction);
} else if (restriction instanceof ValuesRestriction) {
analyseTypes((ValuesRestriction) restriction);
} else if (restriction instanceof Sp4rqlScope) {
// no need to inspect scopes
} else {
throw new ParseException("Unsupported restriction type to analyse");
}
}
}
}
private void analyseTypes(ExpressionUnit expression) {
type.mustBeOneOf(OperatorType.getType(expression.getOperator()));
}
private void analyseTypes(BindRestriction restriction) {
ExpressionArgument expression = restriction.getExpression();
if(expression instanceof VariableToken) {
Sp4rqlSolution other = scope.getSolution((VariableToken) expression);
addEqualSolution(other); // todo: do the same for FILTER ?x = ?y
} else if(expression instanceof ReferenceToken) {
type.mustBeOneOf(SolutionType.NODE, SolutionType.GRAPH, SolutionType.PREDICATE);
} else if(expression instanceof LiteralToken) {
type.mustBeOneOf(SolutionType.LITERAL);
} else if(expression instanceof ExpressionUnit) {
Integer resolvesTo = expression.resolvesTo();
type.mustBeOneOf(resolvesTo);
} else {
throw new ParseException("Do not ask resolvesTo of this restriction type when analysing types");
}
}
private void analyseTypes(SingleTermRestriction restriction) {
if(restriction.inScope() instanceof ScopeSimple) {
Sp4rqlToken graphSelector = ((ScopeSimple) restriction.inScope()).getGraphSelector();
if(binding.equals(graphSelector)) {
type.mustBeOneOf(SolutionType.GRAPH);
}
}
if (binding.equals(restriction.getVariable())) {
type.mustBeOneOf(SolutionType.NODE);
}
}
private void analyseTypes(QuadRestriction restriction) {
if(restriction.inScope() instanceof ScopeSimple) {
Sp4rqlToken graphSelector = ((ScopeSimple) restriction.inScope()).getGraphSelector();
if(binding.equals(graphSelector)) {
type.mustBeOneOf(SolutionType.GRAPH);
}
}
if (binding.equals(restriction.getStatement())) {
if (restriction.getObject() instanceof LiteralToken) {
type.mustBeOneOf(SolutionType.LITERAL_STATEMENT);
} else if (restriction.getObject() instanceof ReferenceToken) {
type.mustBeOneOf(SolutionType.NODE_STATEMENT);
} else {
type.mustBeOneOf(SolutionType.NODE_STATEMENT, SolutionType.LITERAL_STATEMENT);
}
}
if (binding.equals(restriction.getSubject())) {
type.mustBeOneOf(SolutionType.NODE);
}
if (binding.equals(restriction.getPredicate())) {
type.mustBeOneOf(SolutionType.PREDICATE);
}
if (binding.equals(restriction.getObject())) {
type.mustBeOneOf(SolutionType.NODE, SolutionType.LITERAL);
}
}
private void analyseTypes(ValuesRestriction restriction) {
boolean literal = false;
boolean node = false;
if(binding instanceof VariableToken && restriction.getExposedVariables().contains(binding)) {
for(Sp4rqlToken value : restriction.getValues((VariableToken) binding)) {
literal |= (value instanceof LiteralToken);
node |= (value instanceof ReferenceToken);
}
}
if(literal && !node) {
type.mustBeOneOf(SolutionType.LITERAL);
} else if(!literal && node) {
type.mustBeOneOf(SolutionType.NODE, SolutionType.PREDICATE, SolutionType.GRAPH);
} else {
type.mustBeOneOf(SolutionType.LITERAL, SolutionType.NODE, SolutionType.PREDICATE, SolutionType.GRAPH);
}
}
public SolutionType getSolutionType() {
return type;
}
public void tuneEqualSolutions() {
for(Sp4rqlSolution other : equalSolutions) {
type.supplement(other.getSolutionType());
other.getSolutionType().supplement(this.type);
}
}
public HashSet getEqualTokens() {
HashSet set = new HashSet<>();
for(Sp4rqlSolution other : equalSolutions) {
set.add(other.getBinding());
}
return set;
}
@Override
public String toString() {
IndentStringBuilder builder = new IndentStringBuilder();
builder.appendLine(String.format("Type: %s", type));
builder.appendLine(String.format("Binding: %s", binding.toString()));
builder.appendLine("Restrictions:");
for(Sp4rqlRestriction restriction : restrictions) {
builder.appendLine(restriction.getAlias());
}
return builder.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy