blob: f424f7385f15328ab24f0591ad6e9609fd3c6ec7 [file] [log] [blame]
package org.apache.rya.indexing.IndexPlanValidator;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
import org.eclipse.rdf4j.query.algebra.BindingSetAssignment;
import org.eclipse.rdf4j.query.algebra.Filter;
import org.eclipse.rdf4j.query.algebra.Join;
import org.eclipse.rdf4j.query.algebra.Projection;
import org.eclipse.rdf4j.query.algebra.StatementPattern;
import org.eclipse.rdf4j.query.algebra.TupleExpr;
import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor;
import com.google.common.collect.Sets;
public class IndexPlanValidator implements TupleValidator {
private boolean omitCrossProd = false;
public IndexPlanValidator(boolean omitCrossProd) {
this.omitCrossProd = omitCrossProd;
}
public void setOmitCrossProd(boolean omitCrossProd) {
this.omitCrossProd = omitCrossProd;
}
@Override
public boolean isValid(TupleExpr te) {
TupleValidateVisitor tv = new TupleValidateVisitor();
te.visit(tv);
return tv.isValid();
}
public int getValidTupleSize(Iterator<TupleExpr> iter) {
int size = 0;
while(iter.hasNext()) {
if(isValid(iter.next())) {
size++;
}
}
return size;
}
@Override
public Iterator<TupleExpr> getValidTuples(Iterator<TupleExpr> tupleIter) {
final Iterator<TupleExpr> iter = tupleIter;
return new Iterator<TupleExpr>() {
private TupleExpr next = null;
private boolean hasNextCalled = false;
private boolean isEmpty = false;
@Override
public boolean hasNext() {
if (!hasNextCalled && !isEmpty) {
while (iter.hasNext()) {
TupleExpr temp = iter.next();
if (isValid(temp)) {
next = temp;
hasNextCalled = true;
return true;
}
}
isEmpty = true;
return false;
} else {
return !isEmpty;
}
}
@Override
public TupleExpr next() {
if (hasNextCalled) {
hasNextCalled = false;
return next;
} else if(isEmpty) {
throw new NoSuchElementException();
}else {
if (this.hasNext()) {
hasNextCalled = false;
return next;
} else {
throw new NoSuchElementException();
}
}
}
@Override
public void remove() {
throw new UnsupportedOperationException("Cannot delete from iterator!");
}
};
}
private boolean isJoinValid(Join join) {
Set<String> leftBindingNames = join.getLeftArg().getBindingNames();
Set<String> rightBindingNames = join.getRightArg().getBindingNames();
//System.out.println("Left binding names are " + leftBindingNames + " and right binding names are " + rightBindingNames);
if (Sets.intersection(leftBindingNames, rightBindingNames).size() == 0) {
return !omitCrossProd;
} else {
if (join.getRightArg() instanceof ExternalTupleSet) {
return ((ExternalTupleSet) join.getRightArg()).supportsBindingSet(leftBindingNames);
} else {
return true;
}
}
}
public class TupleValidateVisitor extends AbstractQueryModelVisitor<RuntimeException> {
private boolean isValid = true;
public boolean isValid() {
return isValid;
}
@Override
public void meet(Projection node) {
node.getArg().visit(this);
}
@Override
public void meet(StatementPattern node) {
return;
}
public void meet(BindingSetAssignment node) {
return;
}
@Override
public void meet(Filter node) {
node.getArg().visit(this);
}
@Override
public void meet(Join node) {
if (isJoinValid(node)) {
super.meet(node);
} else {
isValid = false;
return;
}
}
}
}