package org.aksw.jena_sparql_api.utils;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.jena.graph.Node;
import org.apache.jena.sparql.algebra.optimize.ExprTransformConstantFold;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.engine.binding.BindingRoot;
import org.apache.jena.sparql.expr.E_LogicalNot;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprTransformer;
import org.apache.jena.sparql.expr.NodeValue;
import org.apache.jena.sparql.graph.NodeTransform;
public class ClauseUtils
{
public static final Set<Expr> TRUE = Collections.<Expr>singleton(NodeValue.TRUE);
public static Map<Var, NodeValue> extractConstantConstraints(Collection<? extends Expr> clause) {
Map<Var, NodeValue> result = new HashMap<>(clause.size());
for(Expr expr : clause) {
Entry<Var, NodeValue> e = ExprUtils.extractConstantConstraint(expr);
if(e != null) {
result.put(e.getKey(), e.getValue());
}
}
return result;
}
/*
* Use ExprIndex.filterByVars instead
public static Set<Clause> filterByVars(Collection<Clause> clauses, Set<Var> requiredVars) {
Set<Clause> result = new HashSet<Clause>();
for(Clause clause : clauses) {
Set<Var> clauseVars = clause.getVarsMentioned();
if(!clauseVars.containsAll(requiredVars)) {
continue;
}
result.add(clause);
}
return result;
}*/
//Iterable<? extends Iterable<? extends Expr>
public static Set<Expr> signaturize(Iterable<? extends Expr> clause) {
Set<Expr> result = StreamSupport.stream(clause.spliterator(), false)
.map(e -> ExprUtils.signaturize(e))
.collect(Collectors.toSet());
return result;
}
public static Set<Set<Expr>> filterByVars(Set<Set<Expr>> clauses, Set<Var> requiredVars) {
Set<Set<Expr>> result = new HashSet<Set<Expr>>();
for(Set<Expr> clause : clauses) {
Set<Var> clauseVars = ClauseUtils.getVarsMentioned(clause);
if(!clauseVars.containsAll(requiredVars)) {
continue;
}
result.add(clause);
}
return result;
}
/**
* false means that it is no satisfiable.
*
* true is actually a 'maybe'
*
* @param clause
* @return
*/
public static boolean isSatisfiable(Set<Expr> clause)
{
for(Expr expr : clause) {
if(expr.equals(NodeValue.FALSE)) {
return false;
}
if(!isSatisfiable(expr)) {
return false;
}
if(expr instanceof E_LogicalNot) {
Expr child = ((E_LogicalNot)expr).getArg();
if(clause.contains(child)) {
return false;
}
}
}
return true;
}
public static boolean isSatisfiable(Expr expr)
{
// NOTE Folding does not detect cases such as E_LogicalAnd(E_Equals(x = y), false)
Expr exprCopy = expr.copySubstitute(BindingRoot.create());
Expr folded = ExprTransformer.transform(new ExprTransformConstantFold(), exprCopy) ;
return !folded.equals(NodeValue.FALSE);
}
public static Set<Var> getVarsMentioned(Iterable<? extends Expr> clause)
{
Set<Var> result = new HashSet<Var>();
for(Expr expr : clause) {
result.addAll(expr.getVarsMentioned());
}
return result;
}
public static Set<Set<Expr>> applyNodeTransformSet(Set<Set<Expr>> clauses, NodeTransform nodeTransform) {
Set<Set<Expr>> result = new HashSet<Set<Expr>>();
for(Set<Expr> clause : clauses) {
Set<Expr> transformedClause = applyNodeTransform(clause, nodeTransform);
result.add(transformedClause);
}
return result;
}
public static Set<Expr> applyNodeTransform(Set<Expr> clause, NodeTransform nodeTransform) {
Set<Expr> result = new HashSet<Expr>();
for(Expr expr : clause) {
Expr transformedExpr = expr.applyNodeTransform(nodeTransform);
result.add(transformedExpr);
}
return result;
}
/*
public static Set<Var> getVarsMentioned(Set<Expr> clause)
{
Set<Var> vars = new HashSet<Var>();
for(Expr expr : clause) {
Set<Var> exprVars = expr.getVarsMentioned();
if(vars.isEmpty()) { // this happens on the first expr
vars.addAll(exprVars);
} else {
vars.retainAll(exprVars);
if(vars.isEmpty()) {
break;
}
}
}
return vars;
}
*/
}