package org.aksw.sparqlify.database;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import org.aksw.jena_sparql_api.normal_form.Clause;
import org.apache.commons.collections.CollectionUtils;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.expr.Expr;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/*
class ExprIndex {
private Multimap<Var, Expr> singleVar = HashMultimap.create();
private
public void add(Expr expr) {
Set<Var> vars = expr.getVarsMentioned();
if(vars.size() == 1) {
singleVar.put(vars.iterator().next(), expr);
}
}
}*/
public abstract class ExprNormalForm {
protected Multimap<Var, Clause> varToClauses = HashMultimap.create();
protected Multimap<Set<Var>, Clause> varsToClauses = HashMultimap.create();
protected Multimap<Expr, Clause> exprToClauses = HashMultimap.create();
//protected Multimap<Set<Var>
// expressions that are part of all clauses
protected Set<Expr> commonExprs = new HashSet<Expr>();
protected Set<Var> varsMentioned = new HashSet<Var>();
public Set<Clause> filterByVars(Set<Var> requiredVars) {
Set<Clause> result = new HashSet<Clause>();
for(Entry<Set<Var>, Collection<Clause>> entry : varsToClauses.asMap().entrySet()) {
Set<Var> clauseVars = entry.getKey();
if(!clauseVars.containsAll(requiredVars)) {
continue;
}
result.addAll(entry.getValue());
}
/*
Collection<Clause> clauses = getClauses();
for(Clause clause : clauses) {
Set<Var> clauseVars = clause.getVarsMentioned();
if(!clauseVars.containsAll(requiredVars)) {
continue;
}
result.add(clause);
}*/
return result;
}
public ExprNormalForm(Collection<Clause> clauses) {
addAll(clauses);
}
private void addAll(Collection<Clause> clauses) {
for(Clause clause : clauses) {
add(clause);
}
}
private boolean add(Clause clause) {
Set<Var> vars = clause.getVarsMentioned();
if(varsToClauses.put(vars, clause)) {
for(Var var : vars) {
varToClauses.put(var, clause);
}
varsMentioned.addAll(vars);
// Map the new exprs to the clauses they appear in
// and update the common exprs map
if(exprToClauses.isEmpty()) {
commonExprs.addAll(clause.getExprs());
} else {
commonExprs.retainAll(clause.getExprs());
}
for(Expr expr : clause.getExprs()) {
exprToClauses.put(expr, clause);
}
return true;
}
return false;
}
/**
* Return all expressions having exactly the specified vars
*
* @param vars
* @return
*/
public Collection<Clause> getExactly(Set<Var> vars) {
return varsToClauses.get(vars);
}
/*
public static <K, V> Set<V> getAll(Map<K, V> map, Collection<?> keys) {
Set<V> result = new HashSet<V>();
float scanFactor = 0.75f;
Collection<V> values = map.values();
if(keys.size() > scanFactor * values.size()) {
for(V clause : values) {
if(CollectionUtils.containsAny(clause.getVarsMentioned(), keys)) {
result.add(clause);
}
}
} else {
// TODO Maybe its always faster to go with this option
for(Object key : keys) {
result.addAll(map.get(key));
}
}
return result;
}*/
public Set<Clause> get(Collection<Var> vars) {
Set<Clause> result = new HashSet<Clause>();
float scanFactor = 0.75f;
Collection<Clause> values = varsToClauses.values();
if(vars.size() > scanFactor * values.size()) {
for(Clause clause : values) {
if(CollectionUtils.containsAny(clause.getVarsMentioned(), vars)) {
result.add(clause);
}
}
} else {
// TODO Maybe its always faster to go with this option
for(Var var : vars) {
result.addAll(varToClauses.get(var));
}
}
return result;
}
public Collection<Clause> get(Var var) {
return varToClauses.get(var);
}
public Collection<Clause> getClauses() {
return varsToClauses.values();
}
@Override
public String toString() {
return varsToClauses.values().toString();
}
public Set<Expr> getCommonExprs() {
return commonExprs;
}
/*
public Set<Expr> getCommonExprs(Var var) {
}*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((varsToClauses == null) ? 0 : varsToClauses.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ExprNormalForm other = (ExprNormalForm) obj;
if (varsToClauses == null) {
if (other.varsToClauses != null)
return false;
} else if (!varsToClauses.equals(other.varsToClauses))
return false;
return true;
}
public int size() {
return varsToClauses.size();
}
public Set<Var> getVarsMentioned() {
return varsMentioned;
}
/*
public Dnf eval(Map<Var, Node> binding) {
}*/
}