com.bigdata.rdf.inf.OwlSameAsPropertiesExpandingIterator Maven / Gradle / Ivy
package com.bigdata.rdf.inf;
import java.util.Arrays;
import org.apache.log4j.Logger;
import com.bigdata.bop.BOp;
import com.bigdata.bop.BOpBase;
import com.bigdata.bop.Constant;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IConstant;
import com.bigdata.bop.IConstraint;
import com.bigdata.bop.IPredicate;
import com.bigdata.bop.IVariable;
import com.bigdata.bop.IVariableOrConstant;
import com.bigdata.bop.Var;
import com.bigdata.bop.constraint.BooleanValueExpression;
import com.bigdata.bop.constraint.Constraint;
import com.bigdata.bop.joinGraph.IEvaluationPlan;
import com.bigdata.bop.joinGraph.IEvaluationPlanFactory;
import com.bigdata.bop.joinGraph.fast.DefaultEvaluationPlanFactory2;
import com.bigdata.btree.IIndex;
import com.bigdata.btree.ITupleIterator;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.internal.IVUtility;
import com.bigdata.rdf.rules.RuleContextEnum;
import com.bigdata.rdf.spo.ISPO;
import com.bigdata.rdf.spo.SPO;
import com.bigdata.rdf.spo.SPOKeyOrder;
import com.bigdata.rdf.spo.SPOPredicate;
import com.bigdata.rdf.store.AbstractTripleStore;
import com.bigdata.relation.accesspath.IAccessPath;
import com.bigdata.relation.rule.IAccessPathExpander;
import com.bigdata.relation.rule.IRule;
import com.bigdata.relation.rule.QueryOptions;
import com.bigdata.relation.rule.Rule;
import com.bigdata.relation.rule.eval.ActionEnum;
import com.bigdata.relation.rule.eval.IJoinNexus;
import com.bigdata.relation.rule.eval.IJoinNexusFactory;
import com.bigdata.relation.rule.eval.ISolution;
import com.bigdata.striterator.ChunkedArrayIterator;
import com.bigdata.striterator.IChunkedOrderedIterator;
import com.bigdata.striterator.IKeyOrder;
public class OwlSameAsPropertiesExpandingIterator implements
IChunkedOrderedIterator {
protected final static Logger log =
Logger.getLogger(OwlSameAsPropertiesExpandingIterator.class);
private final IChunkedOrderedIterator src;
private final IKeyOrder keyOrder;
private final IV s, p, o;
private final AbstractTripleStore db;
private final IV sameAs;
private IChunkedOrderedIterator solutions;
private IAccessPathExpander sameAsSelfExpander;
public OwlSameAsPropertiesExpandingIterator(IV s, IV p, IV o,
AbstractTripleStore db, final IV sameAs,
final IKeyOrder keyOrder) {
this.db = db;
this.s = s;
this.p = p;
this.o = o;
this.sameAs = sameAs;
this.keyOrder = keyOrder;
this.sameAsSelfExpander = new SameAsSelfExpander();
if (p == sameAs) {
// we don't need to run the expander when the predicate is
// owl:sameAs, the forward chainer takes care of that case
this.src = db.getAccessPath(s, p, o).iterator();
} else {
this.src = null;
try {
if (s != null && o != null) {
accessSPO();
} else if (s != null && o == null) {
accessSP();
} else if (s == null && o != null) {
accessPO();
} else if (s == null && o == null) {
accessP();
} else
throw new AssertionError();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
private void accessSPO() throws Exception {
/*
construct S ?p O
where {
?sameS sameAs S .
?sameO sameAs O .
?sameS ?p ?sameO
}
*/
final String SPO = db.getSPORelation().getNamespace();
final IVariable _sameS = Var.var("sameS");
final IVariable _sameO = Var.var("sameO");
final IConstant sameAs = new Constant(this.sameAs);
final IConstant s = new Constant(this.s);
final IConstant o = new Constant(this.o);
final IVariableOrConstant _p =
this.p != null ? new Constant(this.p) : Var.var("p");
final SPOPredicate head = new SPOPredicate(SPO, s, _p, o);
final IRule rule =
new Rule("sameAsSPO", head, new IPredicate[] {
new SPOPredicate(SPO, _sameS, sameAs, s,
sameAsSelfExpander),
new SPOPredicate(SPO, _sameO, sameAs, o,
sameAsSelfExpander),
new SPOPredicate(SPO, _sameS, _p, _sameO) },
QueryOptions.DISTINCT, // distinct
// constraints on the rule.
new IConstraint[] { Constraint.wrap(new RejectSameAsSelf(head.s(), head
.p(), head.o())) });
runQuery(rule);
}
private void accessSP() throws Exception {
/*
construct S ?p ?sameO
where {
?sameS sameAs S .
?sameS ?p ?o .
?o sameAs ?sameO
}
*/
final String SPO = db.getSPORelation().getNamespace();
final IVariable _sameS = Var.var("sameS");
final IVariable _sameO = Var.var("sameO");
final IConstant sameAs = new Constant(this.sameAs);
final IConstant s = new Constant(this.s);
final IVariable _o = Var.var("o");
final IVariableOrConstant _p =
this.p != null ? new Constant(this.p) : Var.var("p");
final SPOPredicate head = new SPOPredicate(SPO, s, _p, _sameO);
final IRule rule =
new Rule("sameAsSP", head, new IPredicate[] {
new SPOPredicate(SPO, _sameS, sameAs, s,
sameAsSelfExpander), // ?s sameAs y
new SPOPredicate(SPO, _sameS, _p, _o), // ?s b ?o -> y b w
new SPOPredicate(SPO, _o, sameAs, _sameO, true,
sameAsSelfExpander) },
QueryOptions.DISTINCT, // distinct
// constraints on the rule.
new IConstraint[] { Constraint.wrap(new RejectSameAsSelf(head.s(), head
.p(), head.o())) });
runQuery(rule);
}
private void accessPO() throws Exception {
/*
construct ?sameS ?p O
where {
?sameO sameAs O .
?s ?p ?sameO .
?s sameAs ?sameS
}
*/
final String SPO = db.getSPORelation().getNamespace();
final IVariable _sameS = Var.var("sameS");
final IVariable _sameO = Var.var("sameO");
final IConstant sameAs = new Constant(this.sameAs);
final IVariable _s = Var.var("s");
final IConstant o = new Constant(this.o);
final IVariableOrConstant _p =
this.p != null ? new Constant(this.p) : Var.var("p");
final SPOPredicate head = new SPOPredicate(SPO, _sameS, _p, o);
final IRule rule =
new Rule("sameAsPO", head, new IPredicate[] {
new SPOPredicate(SPO, _sameO, sameAs, o,
sameAsSelfExpander),
new SPOPredicate(SPO, _s, _p, _sameO),
new SPOPredicate(SPO, _s, sameAs, _sameS, true,
sameAsSelfExpander) },
QueryOptions.DISTINCT, // distinct
// constraints on the rule.
new IConstraint[] { Constraint.wrap(new RejectSameAsSelf(head.s(), head
.p(), head.o())) });
runQuery(rule);
}
private void accessP() throws Exception {
/*
construct ?sameS ?p ?sameO
where {
?s sameAs ?sameS .
?o sameAs ?sameO .
?s ?p ?o
}
*/
final String SPO = db.getSPORelation().getNamespace();
final IVariable _sameS = Var.var("sameS");
final IVariable _sameO = Var.var("sameO");
final IConstant sameAs = new Constant(this.sameAs);
final IVariable _s = Var.var("s");
final IVariable _o = Var.var("o");
final IVariableOrConstant _p =
this.p != null ? new Constant(this.p) : Var.var("p");
final SPOPredicate head = new SPOPredicate(SPO, _sameS, _p, _sameO);
final IRule rule =
new Rule("sameAsP", head, new IPredicate[] {
new SPOPredicate(SPO, _sameS, sameAs, _s, true,
sameAsSelfExpander),
new SPOPredicate(SPO, _sameO, sameAs, _o, true,
sameAsSelfExpander),
new SPOPredicate(SPO, _s, _p, _o) },
QueryOptions.DISTINCT, // distinct
// constraints on the rule.
new IConstraint[] { Constraint.wrap(new RejectSameAsSelf(head.s(), head
.p(), head.o())) });
runQuery(rule);
}
private void runQuery(IRule rule)
throws Exception {
// run the query as a native rule.
final IEvaluationPlanFactory planFactory =
DefaultEvaluationPlanFactory2.INSTANCE;
final IJoinNexusFactory joinNexusFactory =
db.newJoinNexusFactory(RuleContextEnum.HighLevelQuery,
ActionEnum.Query, IJoinNexus.ELEMENT, null, // filter
false, // justify
false, // backchain
planFactory);
final IJoinNexus joinNexus =
joinNexusFactory.newInstance(db.getIndexManager());
if (log.isInfoEnabled()) {
final IEvaluationPlan plan = planFactory.newPlan(joinNexus, rule);
StringBuilder sb = new StringBuilder();
int order[] = plan.getOrder();
for (int i = 0; i < order.length; i++) {
sb.append(order[i]);
if (i < order.length - 1) {
sb.append(",");
}
}
log.info("order: [" + sb.toString() + "]");
}
this.solutions = joinNexus.runQuery(rule);
// this.resolverator = resolverator;
}
public IKeyOrder getKeyOrder() {
if (src != null) {
return src.getKeyOrder();
}
return keyOrder;
}
private ISPO[] chunk;
private int i = 0;
public ISPO[] nextChunk() {
if (src != null) {
return src.nextChunk();
}
final int chunkSize = 10000;
ISPO[] s = new ISPO[chunkSize];
int n = 0;
while (hasNext() && n < chunkSize) {
ISolution solution = solutions.next();
// s[n++] = resolverator.resolve(solution);
ISPO spo = solution.get();
spo = new SPO(spo.s(), spo.p(), spo.o());
s[n++] = spo;
}
// copy so that stmts[] is dense.
ISPO[] stmts = new ISPO[n];
System.arraycopy(s, 0, stmts, 0, n);
// fill in the explicit/inferred information, sort by SPO key order
// since we will use the SPO index to do the value completion
stmts = db.bulkCompleteStatements(stmts);
// resort into desired order
Arrays.sort(stmts, 0, n, this.keyOrder.getComparator());
return stmts;
}
public ISPO[] nextChunk(IKeyOrder keyOrder) {
if (src != null) {
return src.nextChunk(keyOrder);
}
if (keyOrder == null)
throw new IllegalArgumentException();
ISPO[] stmts = nextChunk();
if (this.keyOrder != keyOrder) {
// sort into the required order.
Arrays.sort(stmts, 0, stmts.length, keyOrder.getComparator());
}
return stmts;
}
public ISPO next() {
if (src != null) {
return src.next();
}
if (chunk == null || i == chunk.length) {
chunk = nextChunk();
i = 0;
if (log.isInfoEnabled())
log.info("got a chunk, length = " + chunk.length);
}
return chunk[i++];
}
public void remove() {
if (src != null) {
src.remove();
return;
}
throw new UnsupportedOperationException();
}
public void close() {
if (src != null) {
src.close();
return;
}
if (solutions != null) {
solutions.close();
}
}
public boolean hasNext() {
if (src != null) {
return src.hasNext();
}
if (chunk != null) {
return i < chunk.length;
}
if (solutions != null) {
return solutions.hasNext();
}
return false;
}
private class SameAsSelfExpander implements IAccessPathExpander {
public boolean backchain() {
return false;
}
public boolean runFirst() {
return false;
}
public IAccessPath getAccessPath(
final IAccessPath accessPath) {
return new SameAsSelfAccessPath(accessPath);
}
};
private class SameAsSelfAccessPath implements IAccessPath {
private IAccessPath accessPath;
private SPO spo;
public SameAsSelfAccessPath(IAccessPath accessPath) {
this.accessPath = accessPath;
final IVariableOrConstant p =
accessPath.getPredicate().get(1);
if (!p.isConstant() || !IVUtility.equals(p.get(), sameAs)) {
throw new UnsupportedOperationException("p must be owl:sameAs");
}
}
private IChunkedOrderedIterator getAppender() {
final IVariableOrConstant s =
accessPath.getPredicate().get(0);
final IVariableOrConstant o =
accessPath.getPredicate().get(2);
if (s.isVar() && o.isVar()) {
throw new UnsupportedOperationException(
"s and o cannot both be variables");
}
if (s.isConstant() && o.isConstant()
&& s.get().equals(o.get()) == false) {
/*
* if s and o are both constants, then there is nothing for this
* appender to append, unless they are equal to each other, in
* which case we can append that solution
*/
this.spo = null;
} else {
final IV constant = s.isConstant() ? s.get() : o.get();
this.spo =
s.isConstant() ? new SPO(s.get(), sameAs, constant)
: new SPO(constant, sameAs, o.get());
if (log.isInfoEnabled())
log.info("appending SPO: " + spo.toString(db));
}
if (spo != null) {
return new ChunkedArrayIterator(1, new SPO[] { spo },
SPOKeyOrder.SPO);
} else {
return null;
}
}
@Override
public IIndex getIndex() {
return accessPath.getIndex();
}
@Override
public IKeyOrder getKeyOrder() {
return accessPath.getKeyOrder();
}
@Override
public IPredicate getPredicate() {
return accessPath.getPredicate();
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public IChunkedOrderedIterator iterator() {
final IChunkedOrderedIterator appender = getAppender();
final IChunkedOrderedIterator delegate =
accessPath.iterator();
if (appender == null) {
return delegate;
}
return new IChunkedOrderedIterator() {
public ISPO next() {
if (delegate.hasNext()) {
return delegate.next();
} else {
return appender.next();
}
}
public ISPO[] nextChunk() {
if (delegate.hasNext()) {
return delegate.nextChunk();
} else {
return appender.nextChunk();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
public boolean hasNext() {
return delegate.hasNext() || appender.hasNext();
}
public IKeyOrder getKeyOrder() {
return delegate.getKeyOrder();
}
public ISPO[] nextChunk(IKeyOrder keyOrder) {
if (delegate.hasNext()) {
return delegate.nextChunk(keyOrder);
} else {
return appender.nextChunk(keyOrder);
}
}
public void close() {
delegate.close();
appender.close();
}
};
}
// public IChunkedOrderedIterator iterator(int limit, int capacity) {
// throw new UnsupportedOperationException();
// }
@Override
public IChunkedOrderedIterator iterator(long offset, long limit, int capacity) {
throw new UnsupportedOperationException();
}
@Override
public long rangeCount(boolean exact) {
return accessPath.rangeCount(exact) + 1;
}
// @Override
// public ITupleIterator rangeIterator() {
// throw new UnsupportedOperationException();
// }
@Override
public long removeAll() {
throw new UnsupportedOperationException();
}
};
private class RejectSameAsSelf extends BOpBase implements BooleanValueExpression {
/**
*
*/
private static final long serialVersionUID = -7877904606067597254L;
public RejectSameAsSelf(final IVariableOrConstant _s,
final IVariableOrConstant _p,
final IVariableOrConstant _o) {
super(new BOp[] { _s, _p, _o }, null/*annotations*/);
}
public Boolean get(final IBindingSet bindings) {
final IV sVal = getValue((IVariableOrConstant)get(0/*_s*/), bindings);
final IV pVal = getValue((IVariableOrConstant)get(1/*_p*/), bindings);
final IV oVal = getValue((IVariableOrConstant)get(2/*_o*/), bindings);
// not fully bound yet, just ignore for now
if (sVal == null || pVal == null || oVal == null) {
return true;
}
if (IVUtility.equals(pVal, sameAs) && IVUtility.equals(sVal, oVal)) {
return false;
}
return true;
}
private IV getValue(final IVariableOrConstant _x,
final IBindingSet bindings) {
final IV val;
if (_x.isConstant()) {
val = _x.get();
} else {
final IConstant bound = bindings.get((IVariable) _x);
val = bound != null ? bound.get() : null;
}
return val;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy