com.bigdata.bop.paths.ZeroLengthPathOp Maven / Gradle / Ivy
/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on Aug 25, 2010
*/
package com.bigdata.bop.paths;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import com.bigdata.bop.BOp;
import com.bigdata.bop.BOpContext;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IConstant;
import com.bigdata.bop.IVariable;
import com.bigdata.bop.IVariableOrConstant;
import com.bigdata.bop.NV;
import com.bigdata.bop.PipelineOp;
import com.bigdata.relation.accesspath.IBlockingBuffer;
import cutthecrap.utils.striterators.ICloseableIterator;
/**
* An attempt to solve the zero length path problem with its own operator.
*
* @deprecated Does not work. Leads to cardinality problems and can be removed.
* Zero Length Paths are integrated into the ALP node /
* ArbitraryLengthPathOp now.
*/
public class ZeroLengthPathOp extends PipelineOp {
/**
*
*/
private static final long serialVersionUID = 1L;
public interface Annotations extends PipelineOp.Annotations {
/**
* The left side of the zero-length path.
*/
String LEFT_TERM = Annotations.class.getName() + ".leftTerm";
/**
* The right side of the zero-length path.
*/
String RIGHT_TERM = Annotations.class.getName() + ".rightTerm";
}
/**
* Deep copy constructor.
*
* @param op
*/
public ZeroLengthPathOp(ZeroLengthPathOp op) {
super(op);
}
/**
* Shallow copy constructor.
*
* @param args
* @param annotations
*/
public ZeroLengthPathOp(BOp[] args, Map annotations) {
super(args, annotations);
}
public ZeroLengthPathOp(final BOp[] args, NV... annotations) {
this(args, NV.asMap(annotations));
}
public FutureTask eval(final BOpContext context) {
return new FutureTask(new ZeroLengthPathTask(this, context));
}
static private class ZeroLengthPathTask implements Callable {
private final BOpContext context;
private final IVariable> leftVar, rightVar;
private final IConstant> leftConst, rightConst;
ZeroLengthPathTask(final ZeroLengthPathOp op,
final BOpContext context) {
this.context = context;
final IVariableOrConstant> leftTerm = (IVariableOrConstant>) op
.getProperty(Annotations.LEFT_TERM);
this.leftVar = leftTerm.isVar() ? (IVariable>) leftTerm : null;
this.leftConst = leftTerm.isConstant() ? (IConstant>) leftTerm : null;
final IVariableOrConstant> rightTerm = (IVariableOrConstant>) op
.getProperty(Annotations.RIGHT_TERM);
this.rightVar = rightTerm.isVar() ? (IVariable>) rightTerm : null;
this.rightConst = rightTerm.isConstant() ? (IConstant>) rightTerm : null;
if (leftConst != null && rightConst != null) {
throw new IllegalArgumentException("must be a variable on at least one side");
}
}
public Void call() throws Exception {
// source.
final ICloseableIterator source = context
.getSource();
// default sink
final IBlockingBuffer sink = context.getSink();
try {
while (source.hasNext()) {
final IBindingSet[] chunk = source.next();
final IBindingSet[] chunkOut = processChunk(chunk);
sink.add(chunkOut);
}
// flush the sink.
sink.flush();
// Done.
return null;
} finally {
sink.close();
source.close();
}
}
@SuppressWarnings("unchecked")
private IBindingSet[] processChunk(final IBindingSet[] chunk) {
final IBindingSet[] chunkOut = new IBindingSet[chunk.length];
int j = 0;
for (int i = 0; i < chunk.length; i++) {
final IBindingSet bs = chunk[i].clone();
final Gearing gearing = getGearing(bs);
if (gearing == null) {
// neither side of the zero-length path is bound
return new IBindingSet[0];
}
// first check to see if the variable side is already bound
if (bs.isBound(gearing.var)) {
/*
* If it has a value that is not equals to the constant
* side then we filter out the solution (by not adding it
* to chunkOut).
*/
if (!bs.get(gearing.var).equals(gearing.constant)) {
continue;
}
} else {
// create a zero length path
bs.set(gearing.var, gearing.constant);
}
chunkOut[j++] = bs;
}
if (j != chunk.length) {
final IBindingSet[] tmp = new IBindingSet[j];
System.arraycopy(chunkOut, 0, tmp, 0, j);
return tmp;
} else {
return chunkOut;
}
}
private Gearing getGearing(final IBindingSet bs) {
if (leftConst != null) {
return new Gearing(rightVar, leftConst);
} else if (rightConst != null) {
return new Gearing(leftVar, rightConst);
} else { // both left and right are vars
if (bs.isBound(this.leftVar)) {
return new Gearing(this.rightVar, bs.get(this.leftVar));
} else if (bs.isBound(this.rightVar)) {
return new Gearing(this.leftVar, bs.get(this.rightVar));
} else {
return null;
}
}
}
private class Gearing {
final public IVariable> var;
final public IConstant> constant;
public Gearing(final IVariable> var, final IConstant> constant) {
this.var = var;
this.constant = constant;
}
}
} // class ZeroLengthPathTask
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy