You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rya.apache.org by pu...@apache.org on 2016/06/16 14:04:19 UTC

[08/10] incubator-rya git commit: Added OPTIONAL support for Precomputed-Joins, including support for matching PCJs with OPTIONALs and evaluation of query plans containing PCJs with OPTIONALs.

Added OPTIONAL support for Precomputed-Joins, including support for matching
PCJs with OPTIONALs and evaluation of query plans containing PCJs with OPTIONALs.


Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/96dd55ec
Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/96dd55ec
Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/96dd55ec

Branch: refs/heads/develop
Commit: 96dd55ec505c3e207451702d99a7d296374ff850
Parents: 14073a2
Author: Caleb Meier <me...@gmail.com>
Authored: Mon Apr 11 16:23:04 2016 -0400
Committer: Caleb Meier <me...@gmail.com>
Committed: Mon May 16 18:29:50 2016 -0400

----------------------------------------------------------------------
 .../iterators/BindingSetHashJoinIterator.java   |  324 +++
 .../pcj/iterators/IteratorCombiner.java         |  107 +
 .../PCJKeyToCrossProductBindingSetIterator.java |  267 ++
 .../PCJKeyToJoinBindingSetIterator.java         |  199 ++
 .../accumulo/precompQuery/AccumuloPcjQuery.java |  355 ---
 .../GeneralizedExternalProcessor.java           |    2 +-
 .../IndexedExecutionPlanGenerator.java          |    3 +-
 .../main/java/mvm/rya/indexing/PcjQuery.java    |   40 -
 .../mvm/rya/indexing/accumulo/ConfigUtils.java  |   67 +-
 .../accumulo/entity/AccumuloDocIdIndexer.java   |  119 +-
 .../indexing/external/PrecompJoinOptimizer.java |  883 -------
 .../external/QueryVariableNormalizer.java       | 1180 ---------
 .../external/tupleSet/AccumuloIndexSet.java     |  732 ++++--
 .../external/tupleSet/ExternalTupleSet.java     |   43 +-
 .../tupleSet/SimpleExternalTupleSet.java        |    2 -
 .../pcj/matching/AbstractPCJMatcher.java        |  126 +
 .../pcj/matching/AbstractQuerySegment.java      |  122 +
 .../pcj/matching/FlattenedOptional.java         |  331 +++
 .../rya/indexing/pcj/matching/JoinSegment.java  |  130 +
 .../pcj/matching/JoinSegmentPCJMatcher.java     |  101 +
 .../pcj/matching/OptionalJoinSegment.java       |  146 ++
 .../matching/OptionalJoinSegmentPCJMatcher.java |  142 ++
 .../rya/indexing/pcj/matching/PCJMatcher.java   |   76 +
 .../pcj/matching/PCJMatcherFactory.java         |   73 +
 .../pcj/matching/PCJNodeConsolidator.java       |  628 +++++
 .../rya/indexing/pcj/matching/PCJOptimizer.java |  348 +++
 .../pcj/matching/PCJOptimizerUtilities.java     |  346 +++
 .../pcj/matching/QueryNodesToTupleExpr.java     |  194 ++
 .../rya/indexing/pcj/matching/QuerySegment.java |   83 +
 .../pcj/matching/QueryVariableNormalizer.java   | 1180 +++++++++
 .../pcj/matching/TopOfQueryFilterRelocator.java |   97 +
 .../IndexPlanValidatorTest.java                 |   58 +-
 .../ThreshholdPlanSelectorTest.java             |    4 +-
 .../external/AccumuloPcjIntegrationTest.java    |   17 +-
 .../indexing/external/PCJOptionalTestIT.java    |   31 +-
 .../PrecompJoinOptimizerIntegrationTest.java    |  211 +-
 .../external/PrecompJoinOptimizerTest.java      |  857 +++----
 .../external/PrecompJoinOptimizerTest2.java     |   33 +-
 .../PrecompJoinOptimizerVarToConstTest.java     |   16 +-
 .../external/tupleSet/AccumuloIndexSetTest.java | 2371 +++++++++++++-----
 .../tupleSet/QueryVariableNormalizerTest.java   |    2 +-
 .../VarConstQueryVariableNormalizerTest.java    |    2 +-
 .../pcj/matching/FlattenedOptionalTest.java     |  133 +
 .../pcj/matching/JoinSegmentPCJMatcherTest.java |  214 ++
 .../indexing/pcj/matching/JoinSegmentTest.java  |  204 ++
 .../OptionalJoinSegmentPCJMatcherTest.java      |  274 ++
 .../pcj/matching/OptionalJoinSegmentTest.java   |  122 +
 .../pcj/matching/PCJNodeConsolidatorTest.java   |  459 ++++
 .../indexing/pcj/matching/PCJOptimizerTest.java |  463 ++++
 .../pcj/matching/PCJOptimizerUtilitesTest.java  |   96 +
 50 files changed, 9921 insertions(+), 4092 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/BindingSetHashJoinIterator.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/BindingSetHashJoinIterator.java b/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/BindingSetHashJoinIterator.java
new file mode 100644
index 0000000..0966903
--- /dev/null
+++ b/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/BindingSetHashJoinIterator.java
@@ -0,0 +1,324 @@
+package mvm.rya.accumulo.pcj.iterators;
+
+/*
+ * 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 info.aduna.iteration.CloseableIteration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import mvm.rya.indexing.external.tupleSet.ExternalTupleSet;
+
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.query.algebra.evaluation.QueryBindingSet;
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+
+/**
+ * This {@link CloseableIteration} performs a hash join by joining each
+ * {@link Map.Entry<String, BindingSet>} with all corresponding
+ * {@link BindingSet} in a Multimap with the same String key.
+ *
+ */
+public class BindingSetHashJoinIterator implements
+		CloseableIteration<BindingSet, QueryEvaluationException> {
+
+	//BindingSets passed to PCJ mapped according to values
+	//associated with common variables with table
+	private Multimap<String, BindingSet> bindingJoinVarHash;
+	//BindingSets taken from PCJ table
+	private CloseableIteration<Map.Entry<String, BindingSet>, QueryEvaluationException> joinIter;
+	private Iterator<BindingSet> joinedBindingSets = Collections
+			.emptyIterator();
+	//If PCJ contains LeftJoin, this is a set of variable in LeftJoin.  Used when performing Join.
+	private Set<String> unAssuredVariables;
+	//indicates when HashJoin formed from a single collection of join variable or if the size and
+	//collection of join variables varies -- this is to optimize the join process
+	private HashJoinType type;
+	private final BindingSet EMPTY_BINDINGSET = new QueryBindingSet();
+	private BindingSet next;
+	private boolean hasNextCalled = false;
+	private boolean isEmpty = false;
+
+	/**
+	 * Enum type to indicate whether HashJoin will be performed over a fixed
+	 * subset of variables common to each {@link BindingSet}, or if there is a
+	 * collection of variable subsets over which to join.
+	 *
+	 */
+	public enum HashJoinType {
+		CONSTANT_JOIN_VAR, VARIABLE_JOIN_VAR
+	};
+
+	public BindingSetHashJoinIterator(
+			Multimap<String, BindingSet> bindingJoinVarHash,
+			CloseableIteration<Map.Entry<String, BindingSet>, QueryEvaluationException> joinIter,
+			Set<String> unAssuredVariables, HashJoinType type) {
+		this.bindingJoinVarHash = bindingJoinVarHash;
+		this.joinIter = joinIter;
+		this.type = type;
+		this.unAssuredVariables = unAssuredVariables;
+	}
+
+	@Override
+	public boolean hasNext() throws QueryEvaluationException {
+		if (!hasNextCalled && !isEmpty) {
+			while (joinedBindingSets.hasNext() || joinIter.hasNext()) {
+				if (!joinedBindingSets.hasNext()) {
+					Entry<String, BindingSet> entry = joinIter.next();
+					joinedBindingSets = joinBindingSetEntry(entry);
+				}
+				if (!joinedBindingSets.hasNext()) {
+					continue;
+				}
+				next = joinedBindingSets.next();
+				hasNextCalled = true;
+				return true;
+			}
+
+			isEmpty = true;
+			return false;
+		} else if (isEmpty) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	@Override
+	public BindingSet next() throws QueryEvaluationException {
+		if (hasNextCalled) {
+			hasNextCalled = false;
+		} else if (isEmpty) {
+			throw new NoSuchElementException();
+		} else {
+			if (this.hasNext()) {
+				hasNextCalled = false;
+			} else {
+				throw new NoSuchElementException();
+			}
+		}
+		return next;
+	}
+
+	@Override
+	public void remove() throws QueryEvaluationException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void close() throws QueryEvaluationException {
+		joinIter.close();
+	}
+
+	/**
+	 * This method takes the valOrderString, which is a key used for computing
+	 * hash joins, and generates multiple keys by pulling off one delimiter
+	 * separated component at a time. This is used when the size of the join key
+	 * varies from {@link Map.Entry} to Entry. It allows the BindingSet to be
+	 * joined using all prefixes of the key.
+	 *
+	 * @param valOrderString
+	 *            - key used for hash join
+	 * @return
+	 */
+	private List<String> getValueOrders(String valOrderString) {
+
+		List<String> valueOrders = new ArrayList<>();
+		String[] splitValOrderString = valOrderString
+				.split(ExternalTupleSet.VALUE_DELIM);
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(splitValOrderString[0]);
+		valueOrders.add(buffer.substring(0));
+
+		for (int i = 1; i < splitValOrderString.length; i++) {
+			buffer.append(ExternalTupleSet.VALUE_DELIM + splitValOrderString[i]);
+			valueOrders.add(buffer.substring(0));
+		}
+
+		return valueOrders;
+	}
+
+	/**
+	 * This method verifies that all common variables have a common value and
+	 * then joins the BindingSets together. In the case that the PCJ contains a
+	 * LeftJoin, if the leftBs and rightBs have a common variable with distinct
+	 * values and that common variable is unassured (only appears in LeftJoin),
+	 * this method uses the value corresponding to leftBs.
+	 *
+	 * @param leftBs
+	 *            - BindingSet passed into PCJ
+	 * @param rightBs
+	 *            - PCJ BindingSet
+	 * @return - joined BindingSet
+	 */
+	private BindingSet joinBindingSets(BindingSet leftBs, BindingSet rightBs) {
+
+		Set<String> commonVars = Sets.intersection(leftBs.getBindingNames(),
+				rightBs.getBindingNames());
+		// compare values associated with common variables to make sure
+		// BindingSets can be joined. Possible for leftBs and rightBs
+		// to have a common unAssuredVariable in event PCJ contains LeftJoin.
+		// if values corresponding to common unAssuredVariable do not agree
+		// add value corresponding to leftBs
+		for (String s : commonVars) {
+			if (!leftBs.getValue(s).equals(rightBs.getValue(s))
+					&& !unAssuredVariables.contains(s)) {
+				return EMPTY_BINDINGSET;
+			}
+		}
+		QueryBindingSet bs = new QueryBindingSet(removeConstants(leftBs));
+
+		rightBs = removeConstants(rightBs);
+		// only add Bindings corresponding to variables that have no value
+		// assigned. This takes into account case where leftBs and rightBs
+		// share a common, unAssuredVariable. In this case, use value
+		// corresponding
+		// to leftBs, which is effectively performing a LeftJoin.
+		for (String s : rightBs.getBindingNames()) {
+			if (bs.getValue(s) == null) {
+				bs.addBinding(s, rightBs.getValue(s));
+			}
+		}
+
+		return bs;
+	}
+
+	private BindingSet removeConstants(BindingSet bs) {
+		QueryBindingSet bSet = new QueryBindingSet();
+		for (String s : bs.getBindingNames()) {
+			if (!s.startsWith(ExternalTupleSet.CONST_PREFIX)) {
+				bSet.addBinding(bs.getBinding(s));
+			}
+		}
+		return bSet;
+	}
+
+	/**
+	 * This method returns an Iterator which joins the given Entry's BindingSet
+	 * to all BindingSets which matching the Entry's key.
+	 *
+	 * @param entry - entry to be joined
+	 * @return - Iterator over joined BindingSets
+	 */
+	private Iterator<BindingSet> joinBindingSetEntry(
+			Map.Entry<String, BindingSet> entry) {
+
+		List<Collection<BindingSet>> matches = new ArrayList<>();
+		if (type == HashJoinType.CONSTANT_JOIN_VAR) {
+			if (bindingJoinVarHash.containsKey(entry.getKey())) {
+				matches.add(bindingJoinVarHash.get(entry.getKey()));
+			}
+		} else {
+			List<String> valOrders = getValueOrders(entry.getKey());
+			for (String s : valOrders) {
+				if (bindingJoinVarHash.containsKey(s)) {
+					matches.add(bindingJoinVarHash.get(s));
+				}
+			}
+		}
+
+		if (matches.size() == 0) {
+			return Collections.emptyIterator();
+		} else {
+			return new BindingSetCollectionsJoinIterator(entry.getValue(),
+					matches);
+		}
+
+	}
+
+	/**
+	 * Given a BindingSet and a List of Collections of BindingSets, this
+	 * Iterator joins the BindingSet with the BindingSets in each Collection
+	 *
+	 */
+	private class BindingSetCollectionsJoinIterator implements
+			Iterator<BindingSet> {
+
+		private Iterator<Collection<BindingSet>> collectionIter;
+		private Iterator<BindingSet> bsIter = Collections.emptyIterator();
+		private BindingSet next;
+		private BindingSet joinBs;
+		private boolean hasNextCalled = false;
+		private boolean isEmpty = false;
+
+		public BindingSetCollectionsJoinIterator(BindingSet bs,
+				List<Collection<BindingSet>> collection) {
+			this.collectionIter = collection.iterator();
+			this.joinBs = bs;
+		}
+
+		@Override
+		public boolean hasNext() {
+
+			if (!hasNextCalled && !isEmpty) {
+				while (bsIter.hasNext() || collectionIter.hasNext()) {
+					if (!bsIter.hasNext()) {
+						bsIter = collectionIter.next().iterator();
+					}
+					next = joinBindingSets(bsIter.next(), joinBs);
+					if (next == EMPTY_BINDINGSET) {
+						continue;
+					}
+					hasNextCalled = true;
+					return true;
+				}
+				isEmpty = true;
+				return false;
+			} else if (isEmpty) {
+				return false;
+			} else {
+				return true;
+			}
+		}
+
+		@Override
+		public BindingSet next() {
+			if (hasNextCalled) {
+				hasNextCalled = false;
+			} else if (isEmpty) {
+				throw new NoSuchElementException();
+			} else {
+				if (this.hasNext()) {
+					hasNextCalled = false;
+				} else {
+					throw new NoSuchElementException();
+				}
+			}
+			return next;
+		}
+
+		@Override
+		public void remove() {
+			throw new UnsupportedOperationException();
+		}
+
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/IteratorCombiner.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/IteratorCombiner.java b/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/IteratorCombiner.java
new file mode 100644
index 0000000..2407865
--- /dev/null
+++ b/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/IteratorCombiner.java
@@ -0,0 +1,107 @@
+package mvm.rya.accumulo.pcj.iterators;
+
+/*
+ * 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 info.aduna.iteration.CloseableIteration;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.QueryEvaluationException;
+
+import com.google.common.base.Preconditions;
+
+/**
+ *	This {@link CloseableIteration} takes in a list of CloseableIterations
+ *	and merges them together into a single CloseableIteration.
+ *
+ */
+public class IteratorCombiner implements
+		CloseableIteration<BindingSet, QueryEvaluationException> {
+
+
+	private Collection<CloseableIteration<BindingSet, QueryEvaluationException>> iterators;
+	private Iterator<CloseableIteration<BindingSet, QueryEvaluationException>> iteratorIterator;
+	private CloseableIteration<BindingSet, QueryEvaluationException> currIter;
+	private boolean isEmpty = false;
+	private boolean hasNextCalled = false;
+	private BindingSet next;
+
+	public IteratorCombiner(Collection<CloseableIteration<BindingSet, QueryEvaluationException>> iterators) {
+		Preconditions.checkArgument(iterators.size() > 0);
+		this.iterators = iterators;
+		iteratorIterator = iterators.iterator();
+		currIter = iteratorIterator.next();
+	}
+
+	@Override
+	public boolean hasNext() throws QueryEvaluationException {
+		if (!hasNextCalled && !isEmpty) {
+			while (currIter.hasNext() || iteratorIterator.hasNext()) {
+				if(!currIter.hasNext()) {
+					currIter = iteratorIterator.next();
+				}
+				if(!currIter.hasNext()) {
+					continue;
+				}
+				next = currIter.next();
+				hasNextCalled = true;
+				return true;
+			}
+			isEmpty = true;
+			return false;
+		} else if (isEmpty) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	@Override
+	public BindingSet next() throws QueryEvaluationException {
+		if (hasNextCalled) {
+			hasNextCalled = false;
+		} else if (isEmpty) {
+			throw new NoSuchElementException();
+		} else {
+			if (this.hasNext()) {
+				hasNextCalled = false;
+			} else {
+				throw new NoSuchElementException();
+			}
+		}
+		return next;
+	}
+
+	@Override
+	public void remove() throws QueryEvaluationException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void close() throws QueryEvaluationException {
+		for(CloseableIteration<BindingSet, QueryEvaluationException> iterator: iterators) {
+			iterator.close();
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/PCJKeyToCrossProductBindingSetIterator.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/PCJKeyToCrossProductBindingSetIterator.java b/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/PCJKeyToCrossProductBindingSetIterator.java
new file mode 100644
index 0000000..0c7369c
--- /dev/null
+++ b/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/PCJKeyToCrossProductBindingSetIterator.java
@@ -0,0 +1,267 @@
+package mvm.rya.accumulo.pcj.iterators;
+
+/*
+ * 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 info.aduna.iteration.CloseableIteration;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import mvm.rya.indexing.external.tupleSet.ExternalTupleSet;
+
+import org.apache.accumulo.core.client.Scanner;
+import org.apache.accumulo.core.data.Key;
+import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjSerializer;
+import org.apache.rya.indexing.pcj.storage.accumulo.BindingSetConverter.BindingSetConversionException;
+import org.apache.rya.indexing.pcj.storage.accumulo.VariableOrder;
+import org.openrdf.model.Value;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.query.algebra.evaluation.QueryBindingSet;
+
+import com.google.common.collect.HashBiMap;
+
+/**
+ *	This class takes in a {@link Scanner} and a Collection of BindingSets,
+ *	deserializes each {@link Map.Entry<Key,Value>} taken from the Scanner into
+ *  a {@link BindingSet}, and performs a cross product on the BindingSet with
+ *  each BindingSet in the provided Collection.  The user can also specify a
+ *  {@link Map<String, Value>} of constant constraints that can be used to filter.
+ *
+ */
+public class PCJKeyToCrossProductBindingSetIterator implements
+		CloseableIteration<BindingSet, QueryEvaluationException> {
+
+	//BindingSets passed to PCJ used to form cross product
+	private List<BindingSet> crossProductBs;
+	//Scanner over PCJ table
+	private Scanner scanner;
+	//Iterator over PCJ scanner
+	private Iterator<Map.Entry<Key, org.apache.accumulo.core.data.Value>> iterator;
+	//Map of PCJ variables in table to variable in query
+	private Map<String, String> pcjVarMap;
+	//if PCJ contains LeftJoin, this is a set of variables that only appear in
+	//LeftJoin.  Used when performing the cross product.
+	private Set<String> unAssuredVariables;
+	private final AccumuloPcjSerializer converter = new AccumuloPcjSerializer();
+	private final BindingSet EMPTY_BINDINGSET = new QueryBindingSet();
+	private Iterator<BindingSet> crossProductIter = Collections.emptyIterator();
+	private Map<String, Value> constantConstraints;
+	private BindingSet next;
+	private boolean hasNextCalled = false;
+	private boolean isEmpty = false;
+	private boolean crossProductBsExist = false;
+	private boolean constantConstraintsExist = false;
+
+	public PCJKeyToCrossProductBindingSetIterator(Scanner scanner,
+			List<BindingSet> crossProductBs,
+			Map<String, Value> constantConstraints, Set<String> unAssuredVariables,
+			Map<String, String> pcjVarMap) {
+		this.crossProductBs = crossProductBs;
+		this.scanner = scanner;
+		this.iterator = scanner.iterator();
+		this.pcjVarMap = HashBiMap.create(pcjVarMap).inverse();
+		this.constantConstraints = constantConstraints;
+		this.crossProductBsExist = crossProductBs.size() > 0;
+		this.constantConstraintsExist = constantConstraints.size() > 0;
+		this.unAssuredVariables = unAssuredVariables;
+	}
+
+	@Override
+	public boolean hasNext() throws QueryEvaluationException {
+		if (!hasNextCalled && !isEmpty) {
+			if (crossProductBsExist) {
+				while (crossProductIter.hasNext() || iterator.hasNext()) {
+					if (!crossProductIter.hasNext()) {
+						Key key = iterator.next().getKey();
+						try {
+							crossProductIter = getCrossProducts(getBindingSet(key));
+						} catch (BindingSetConversionException e) {
+							throw new QueryEvaluationException(e);
+						}
+					}
+					if (!crossProductIter.hasNext()) {
+						continue;
+					}
+					next = crossProductIter.next();
+					hasNextCalled = true;
+					return true;
+				}
+			} else {
+				while (iterator.hasNext()) {
+					Key key = iterator.next().getKey();
+					try {
+						next = getBindingSet(key);
+					} catch (BindingSetConversionException e) {
+						throw new QueryEvaluationException(e);
+					}
+					//BindingSet cannot be deserialized or is filtered
+					//out by constant constraints
+					if (next == null || next == EMPTY_BINDINGSET) {
+						continue;
+					}
+					hasNextCalled = true;
+					return true;
+				}
+			}
+			isEmpty = true;
+			return false;
+		} else if (isEmpty) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	@Override
+	public BindingSet next() throws QueryEvaluationException {
+		if (hasNextCalled) {
+			hasNextCalled = false;
+		} else if (isEmpty) {
+			throw new NoSuchElementException();
+		} else {
+			if (this.hasNext()) {
+				hasNextCalled = false;
+			} else {
+				throw new NoSuchElementException();
+			}
+		}
+		return next;
+	}
+
+	@Override
+	public void remove() throws QueryEvaluationException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void close() throws QueryEvaluationException {
+		scanner.close();
+	}
+
+	/**
+	 *
+	 * @param key
+	 *            - Accumulo key obtained from scan
+	 * @return - BindingSet satisfying any specified constant constraints
+	 * @throws BindingSetConversionException
+	 * @throws QueryEvaluationException
+	 */
+	private BindingSet getBindingSet(Key key)
+			throws BindingSetConversionException, QueryEvaluationException {
+		byte[] row = key.getRow().getBytes();
+		String[] varOrder = key.getColumnFamily().toString()
+				.split(ExternalTupleSet.VAR_ORDER_DELIM);
+
+		BindingSet bindingSet = converter.convert(row, new VariableOrder(
+				varOrder));
+
+		QueryBindingSet bs = new QueryBindingSet();
+		for (String var : bindingSet.getBindingNames()) {
+			String mappedVar = null;
+			if(pcjVarMap.containsKey(var)) {
+				mappedVar = pcjVarMap.get(var);
+			} else {
+				throw new QueryEvaluationException("PCJ Variable has no mapping to query variable.");
+			}
+			if (constantConstraintsExist) {
+				if (mappedVar.startsWith(ExternalTupleSet.CONST_PREFIX)
+						&& constantConstraints.containsKey(mappedVar)
+						&& !constantConstraints.get(mappedVar).equals(
+								bindingSet.getValue(var))) {
+					return EMPTY_BINDINGSET;
+				}
+			}
+
+			if (!mappedVar.startsWith(ExternalTupleSet.CONST_PREFIX)) {
+					bs.addBinding(mappedVar, bindingSet.getValue(var));
+			}
+		}
+		return bs;
+	}
+
+	/**
+	 * This method forms the cross-product between an input BindingSet and the
+	 * BindingSets contained in crossProdcutBs.
+	 *
+	 * @param bs
+	 *            - {@link BindingSet} used to form cross product with
+	 *            cross-product BindingSets
+	 * @return - Iterator over resulting cross-product
+	 */
+	private Iterator<BindingSet> getCrossProducts(BindingSet bs) {
+		Set<BindingSet> crossProducts = new HashSet<BindingSet>();
+
+		for (BindingSet bSet : crossProductBs) {
+			BindingSet prod = takeCrossProduct(bSet, bs);
+			if (prod != EMPTY_BINDINGSET) {
+				crossProducts.add(prod);
+			}
+		}
+
+		return crossProducts.iterator();
+
+	}
+
+	/**
+	 * This method compute the cross product of the BindingSet passed to the PCJ
+	 * and the PCJ BindingSet.  It verifies that only common variables are unassured
+	 * variables, and if leftBs and rightBs have distinct values for a given variable,
+	 * this method uses the value from leftBs in the cross product BindingSet - this
+	 * is effectively performing a LeftJoin.
+	 *
+	 * @param leftBs - BindingSet passed to PCJ
+	 * @param rightBs - PCJ BindingSet
+	 * @return - cross product BindingSet
+	 */
+	private BindingSet takeCrossProduct(BindingSet leftBs, BindingSet rightBs) {
+		if (bindingSetsIntersect(leftBs, rightBs)) {
+			return EMPTY_BINDINGSET;
+		}
+		QueryBindingSet bs = new QueryBindingSet(leftBs);
+
+		//only add Bindings corresponding to variables that have no value
+		//assigned.  This takes into account case where leftBs and rightBs
+		//share a common, unAssuredVariable.  In this case, use value corresponding
+		//to leftBs, which is effectively performing a LeftJoin.
+		for(String s: rightBs.getBindingNames()) {
+			if(bs.getValue(s) == null) {
+				bs.addBinding(s, rightBs.getValue(s));
+			}
+		}
+		return bs;
+	}
+
+	private boolean bindingSetsIntersect(BindingSet bs1, BindingSet bs2) {
+
+		for(String s: bs1.getBindingNames()) {
+			if(bs2.getValue(s) != null && !unAssuredVariables.contains(s)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/PCJKeyToJoinBindingSetIterator.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/PCJKeyToJoinBindingSetIterator.java b/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/PCJKeyToJoinBindingSetIterator.java
new file mode 100644
index 0000000..1b821d4
--- /dev/null
+++ b/extras/indexing/src/main/java/mvm/rya/accumulo/pcj/iterators/PCJKeyToJoinBindingSetIterator.java
@@ -0,0 +1,199 @@
+package mvm.rya.accumulo.pcj.iterators;
+
+/*
+ * 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 info.aduna.iteration.CloseableIteration;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+
+import mvm.rya.api.RdfCloudTripleStoreUtils;
+import mvm.rya.indexing.external.tupleSet.ExternalTupleSet;
+
+import org.apache.accumulo.core.client.BatchScanner;
+import org.apache.accumulo.core.client.Scanner;
+import org.apache.accumulo.core.data.Key;
+import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjSerializer;
+import org.apache.rya.indexing.pcj.storage.accumulo.BindingSetConverter.BindingSetConversionException;
+import org.apache.rya.indexing.pcj.storage.accumulo.VariableOrder;
+import org.openrdf.model.Value;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.query.algebra.evaluation.QueryBindingSet;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashBiMap;
+
+/**
+ * This class takes in a {@link Scanner} and a Collection of BindingSets,
+ * deserializes each {@link Map.Entry<Key,Value>} taken from the Scanner into a
+ * {@link BindingSet}, and creates a {@link Map.Entry<String, BindingSet>}
+ * object to perform as hash join. The user can also specify a {@link Map
+ * <String, Value>} of constant constraints that can be used to filter.
+ *
+ */
+public class PCJKeyToJoinBindingSetIterator
+		implements
+		CloseableIteration<Map.Entry<String, BindingSet>, QueryEvaluationException> {
+
+	//map of variables as they appear in PCJ table to query variables
+	private Map<String, String> pcjVarMap;
+	//constant constraints used for filtering
+	private Map<String, Value> constantConstraints;
+	//max number of variables an entry in the batch of BindingSets had in common with PCJ
+	//this is used for constructing hash join key.
+	private int maxPrefixLen;
+	private static final AccumuloPcjSerializer converter = new AccumuloPcjSerializer();
+	private final Map.Entry<String, BindingSet> EMPTY_ENTRY = new RdfCloudTripleStoreUtils.CustomEntry<String, BindingSet>(
+			"", new QueryBindingSet());
+	private Iterator<Entry<Key, org.apache.accumulo.core.data.Value>> iterator;
+	private boolean hasNextCalled = false;
+	private boolean isEmpty = false;
+	private Map.Entry<String, BindingSet> next;
+	private BatchScanner scanner;
+
+	public PCJKeyToJoinBindingSetIterator(BatchScanner scanner,
+			Map<String, String> pcjVarMap,
+			Map<String, Value> constantConstraints, int maxPrefixLen) {
+		Preconditions.checkNotNull(scanner);
+		Preconditions.checkArgument(pcjVarMap.size() > 0,
+				"Variable map must contain at least one variable!");
+		Preconditions.checkNotNull(constantConstraints,
+				"Constant constraints cannot be null.");
+		Preconditions.checkArgument(maxPrefixLen > 0,
+				"Max prefix length must be greater than 0.");
+		Preconditions
+				.checkArgument(maxPrefixLen <= pcjVarMap.size(),
+						"Max prefix length must be less than total number of binding names.");
+		this.scanner = scanner;
+		this.pcjVarMap = HashBiMap.create(pcjVarMap).inverse();
+		this.constantConstraints = constantConstraints;
+		this.maxPrefixLen = maxPrefixLen;
+		this.iterator = scanner.iterator();
+
+	}
+
+	public PCJKeyToJoinBindingSetIterator(BatchScanner scanner,
+			Map<String, String> pcjVarMap, int maxPrefixLen) {
+		this(scanner, pcjVarMap, new HashMap<String, Value>(), maxPrefixLen);
+	}
+
+	@Override
+	public boolean hasNext() throws QueryEvaluationException {
+
+		if (!hasNextCalled && !isEmpty) {
+			while (iterator.hasNext()) {
+				Key key = iterator.next().getKey();
+				// get bindings from scan without values associated with
+				// constant constraints
+				try {
+					next = getBindingSetEntryAndMatchConstants(key);
+				} catch (BindingSetConversionException e) {
+					throw new QueryEvaluationException(
+							"Could not deserialize PCJ BindingSet.");
+				}
+				// skip key if constant constraint don't match
+				if (next == EMPTY_ENTRY) {
+					continue;
+				}
+				hasNextCalled = true;
+				return true;
+			}
+			isEmpty = true;
+			return false;
+		} else if (isEmpty) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	@Override
+	public Entry<String, BindingSet> next() throws QueryEvaluationException {
+		if (hasNextCalled) {
+			hasNextCalled = false;
+		} else if (isEmpty) {
+			throw new NoSuchElementException();
+		} else {
+			if (this.hasNext()) {
+				hasNextCalled = false;
+			} else {
+				throw new NoSuchElementException();
+			}
+		}
+		return next;
+	}
+
+	@Override
+	public void remove() throws QueryEvaluationException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void close() throws QueryEvaluationException {
+		scanner.close();
+	}
+
+	/**
+	 *
+	 * @param key
+	 *            - Accumulo key obtained from scan
+	 * @return - Entry<String,BindingSet> satisfying the constant constraints
+	 * @throws BindingSetConversionException
+	 */
+	private Map.Entry<String, BindingSet> getBindingSetEntryAndMatchConstants(
+			Key key) throws BindingSetConversionException {
+		byte[] row = key.getRow().getBytes();
+		String[] varOrder = key.getColumnFamily().toString()
+				.split(ExternalTupleSet.VAR_ORDER_DELIM);
+
+		BindingSet bindingSet = converter.convert(row, new VariableOrder(
+				varOrder));
+
+		QueryBindingSet bs = new QueryBindingSet();
+		for (String var : bindingSet.getBindingNames()) {
+			String mappedVar = pcjVarMap.get(var);
+			if (mappedVar.startsWith(ExternalTupleSet.CONST_PREFIX)
+					&& constantConstraints.containsKey(mappedVar)
+					&& !constantConstraints.get(mappedVar).equals(
+							bindingSet.getValue(var))) {
+				return EMPTY_ENTRY;
+			} else {
+				bs.addBinding(mappedVar, bindingSet.getValue(var));
+			}
+		}
+
+		String orderedValueString = bindingSet.getValue(varOrder[0]).toString();
+		for (int i = 1; i < maxPrefixLen; i++) {
+			Value value = bindingSet.getValue(varOrder[i]);
+			if (value != null) {
+				orderedValueString = orderedValueString
+						+ ExternalTupleSet.VALUE_DELIM + value.toString();
+			}
+		}
+
+		return new RdfCloudTripleStoreUtils.CustomEntry<String, BindingSet>(
+				orderedValueString, bs);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/accumulo/precompQuery/AccumuloPcjQuery.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/accumulo/precompQuery/AccumuloPcjQuery.java b/extras/indexing/src/main/java/mvm/rya/accumulo/precompQuery/AccumuloPcjQuery.java
deleted file mode 100644
index f6b7819..0000000
--- a/extras/indexing/src/main/java/mvm/rya/accumulo/precompQuery/AccumuloPcjQuery.java
+++ /dev/null
@@ -1,355 +0,0 @@
-package mvm.rya.accumulo.precompQuery;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import org.apache.accumulo.core.client.BatchScanner;
-import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.TableNotFoundException;
-import org.apache.accumulo.core.data.Key;
-import org.apache.accumulo.core.data.Range;
-import org.apache.accumulo.core.data.Value;
-import org.apache.accumulo.core.security.Authorizations;
-import org.apache.hadoop.io.Text;
-import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjSerializer;
-import org.apache.rya.indexing.pcj.storage.accumulo.BindingSetConverter.BindingSetConversionException;
-import org.apache.rya.indexing.pcj.storage.accumulo.VariableOrder;
-import org.openrdf.query.BindingSet;
-import org.openrdf.query.QueryEvaluationException;
-import org.openrdf.query.algebra.evaluation.QueryBindingSet;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-/*
- * 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 info.aduna.iteration.CloseableIteration;
-import info.aduna.iteration.Iteration;
-import mvm.rya.api.resolver.RyaTypeResolverException;
-import mvm.rya.indexing.PcjQuery;
-import mvm.rya.indexing.external.tupleSet.AccumuloIndexSet;
-import mvm.rya.indexing.external.tupleSet.ExternalTupleSet;
-
-/**
- * This class encapsulates how pre-computed join tables are used during query
- * evaluation. The method
- * {@link AccumuloPcjQuery#queryPrecompJoin(List, String, Map, Map, Collection)
- * is used by {@link AccumuloIndexSet#evaluate(BindingSet)} to evaluate the
- * {@link AccumuloIndexSet#getTupleExpr()} associated with the Accumulo
- * pre-computed join table. Given the {@link BindingSet} constraints, it uses
- * the variables common to the BindingSet constraints and the pre-computed join
- * table TupleExpr to build a {@Range} prefix to scan the pre-computed
- * join table to obtain results for the constrained sub-query.
- *
- */
-public class AccumuloPcjQuery implements PcjQuery {
-	private static final AccumuloPcjSerializer converter = new AccumuloPcjSerializer();
-
-	private final Connector accCon;
-	private final String tableName;
-
-	public AccumuloPcjQuery(Connector accCon, String tableName) {
-		this.accCon = accCon;
-		this.tableName = tableName;
-	}
-
-	/**
-	 * @param commonVars - variables common to bsConstraints and table in terms of query variables
-	 * @param localityGroup - the column family to scan in terms of table variables
-	 * @param valMap - Literal type associated with constant constraints
-	 * @param varMap - map query variables to pre-computed join table variables
-	 * @param bsConstraints - binding set constraints
-	 * @return {@link Iteration} over result BindingSets
-	 */
-	@Override
-	public CloseableIteration<BindingSet, QueryEvaluationException> queryPrecompJoin(
-			List<String> commonVars, String localityGroup,
-			Map<String, org.openrdf.model.Value> valMap,
-			Map<String, String> varMap, Collection<BindingSet> bsConstraints)
-			throws QueryEvaluationException, TableNotFoundException {
-
-		final Iterator<Entry<Key, Value>> accIter;
-		final Map<String, org.openrdf.model.Value> constValMap = valMap;
-		final HashMultimap<Range, BindingSet> map = HashMultimap.create();
-
-		final List<BindingSet> extProdList = Lists.newArrayList();
-		final List<String> prefixVars = commonVars;
-		final BatchScanner bs = accCon.createBatchScanner(tableName,
-				new Authorizations(), 10);
-		final Set<Range> ranges = Sets.newHashSet();
-		final Map<String, String> tableVarMap = varMap;
-		final boolean bsContainsPrefixVar = bindingsContainsPrefixVar(
-				bsConstraints, prefixVars);
-
-		bs.fetchColumnFamily(new Text(localityGroup));
-		// process bindingSet and constant constraints
-		for (final BindingSet bSet : bsConstraints) {
-			// bindings sets and PCJ have common vars
-			if (bsContainsPrefixVar) {
-				byte[] rangePrefix = null;
-				final QueryBindingSet rangeBs = new QueryBindingSet();
-				for (final String var : prefixVars) {
-					if (var.startsWith(ExternalTupleSet.CONST_PREFIX)) {
-						rangeBs.addBinding(var, constValMap.get(var));
-					} else {
-						rangeBs.addBinding(var, bSet.getBinding(var).getValue());
-					}
-				}
-				try {
-					rangePrefix = converter.convert(rangeBs, new VariableOrder(commonVars));
-				} catch (final BindingSetConversionException e) {
-					throw new QueryEvaluationException(e);
-				}
-				final Range r = Range.prefix(new Text(rangePrefix));
-				map.put(r, bSet);
-				ranges.add(r);
-				// non-empty binding sets and no common vars with no constant
-				// constraints
-			} else if (bSet.size() > 0 && prefixVars.size() == 0) {
-				extProdList.add(bSet);
-			}
-		}
-
-		// constant constraints and no bindingSet constraints
-		// add range of entire table if no constant constraints and
-		// bsConstraints consists of single, empty set (occurs when AIS is
-		// first node evaluated in query)
-		if (ranges.isEmpty()) {
-			// constant constraints
-			if (prefixVars.size() > 0) {
-				byte[] rangePrefix = null;
-				final QueryBindingSet rangeBs = new QueryBindingSet();
-				for (final String var : prefixVars) {
-					if (var.startsWith(ExternalTupleSet.CONST_PREFIX)) {
-						rangeBs.addBinding(var, constValMap.get(var));
-					}
-				}
-				try {
-					rangePrefix = converter.convert(rangeBs, new VariableOrder(commonVars));
-				} catch (final BindingSetConversionException e) {
-					throw new QueryEvaluationException(e);
-				}
-				final Range r = Range.prefix(new Text(rangePrefix));
-				ranges.add(r);
-			}
-			// no constant or bindingSet constraints
-			else {
-				ranges.add(new Range("", true, "~", false));
-			}
-		}
-
-		if (ranges.size() == 0) {
-			accIter = null;
-		} else {
-			bs.setRanges(ranges);
-			accIter = bs.iterator();
-		}
-		return new CloseableIteration<BindingSet, QueryEvaluationException>() {
-			@Override
-			public void remove() throws QueryEvaluationException {
-				throw new UnsupportedOperationException();
-			}
-
-			private Iterator<BindingSet> inputSet = null;
-			private QueryBindingSet currentSolutionBs = null;
-			private boolean hasNextCalled = false;
-			private boolean isEmpty = false;
-
-			@Override
-			public BindingSet next() throws QueryEvaluationException {
-				final QueryBindingSet bs = new QueryBindingSet();
-				if (hasNextCalled) {
-					hasNextCalled = false;
-					if (inputSet != null) {
-						bs.addAll(inputSet.next());
-					}
-					bs.addAll(currentSolutionBs);
-				} else if (isEmpty) {
-					throw new NoSuchElementException();
-				} else {
-					if (this.hasNext()) {
-						hasNextCalled = false;
-						if (inputSet != null) {
-							bs.addAll(inputSet.next());
-						}
-						bs.addAll(currentSolutionBs);
-					} else {
-						throw new NoSuchElementException();
-					}
-				}
-				return bs;
-			}
-
-			@Override
-			public boolean hasNext() throws QueryEvaluationException {
-				if (accIter == null) {
-					isEmpty = true;
-					return false;
-				}
-				if (!hasNextCalled && !isEmpty) {
-					while (accIter.hasNext() || inputSet != null
-							&& inputSet.hasNext()) {
-						if (inputSet != null && inputSet.hasNext()) {
-							hasNextCalled = true;
-							return true;
-						}
-						final Key k = accIter.next().getKey();
-						// get bindings from scan without values associated with
-						// constant constraints
-						BindingSet bs;
-						try {
-							bs = getBindingSetWithoutConstants(k, tableVarMap);
-						} catch (final BindingSetConversionException e) {
-							throw new QueryEvaluationException(e);
-						}
-						currentSolutionBs = new QueryBindingSet();
-						currentSolutionBs.addAll(bs);
-
-						// check to see if additional bindingSet constraints
-						// exist in map
-						if (map.size() > 0) {
-							// get prefix range to retrieve remainder of
-							// bindingSet from map
-							byte[] rangePrefix;
-							try {
-								rangePrefix = getPrefixByte(bs, constValMap,
-										prefixVars);
-							} catch (final BindingSetConversionException e) {
-								throw new QueryEvaluationException(e);
-							}
-							final Range r = Range.prefix(new Text(rangePrefix));
-							inputSet = map.get(r).iterator();
-							if (!inputSet.hasNext()) {
-								continue;
-							} else {
-								hasNextCalled = true;
-								return true;
-							}
-							// check to see if binding set constraints exist,
-							// but no common vars
-						} else if (extProdList.size() > 0) {
-							inputSet = extProdList.iterator();
-							hasNextCalled = true;
-							return true;
-						}
-						// no bindingsSet constraints--only constant constraints
-						// or none
-						else {
-							hasNextCalled = true;
-							return true;
-						}
-					}
-					isEmpty = true;
-					return false;
-				} else if (isEmpty) {
-					return false;
-				} else {
-					return true;
-				}
-			}
-
-			@Override
-			public void close() throws QueryEvaluationException {
-				bs.close();
-			}
-		};
-	}
-
-	/**
-	 *
-	 * @param bindingSets - binding set constraints
-	 * @param prefixVars - common prefix variables to table and any constant constraints
-	 * @return true if there are variables common to binding sets and table and false
-	 * if prefixVars only consists of constant constraints
-	 */
-	private boolean bindingsContainsPrefixVar(
-			Collection<BindingSet> bindingSets, List<String> prefixVars) {
-		final Iterator<BindingSet> iter = bindingSets.iterator();
-		if (iter.hasNext()) {
-			final BindingSet tempBindingSet = iter.next();
-			final Set<String> bindings = tempBindingSet.getBindingNames();
-			for (final String var : prefixVars) {
-				if (bindings.contains(var)) {
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	/**
-	 *
-	 * @param bs - binding set from which byte is extracted
-	 * @param valMap - map which associated Value type to constant constraint
-	 * @param prefixVars - prefix of variables common to binding sets and table and constant constraints
-	 * @return - bytes associated with values in bs that are associated with prefixVars
-	 * @throws RyaTypeResolverException
-	 */
-	private static byte[] getPrefixByte(BindingSet bs,
-			Map<String, org.openrdf.model.Value> valMap, List<String> prefixVars)
-			throws BindingSetConversionException {
-		final QueryBindingSet bSet = new QueryBindingSet();
-		for (final String var : prefixVars) {
-			if (var.startsWith(ExternalTupleSet.CONST_PREFIX)) {
-				bSet.addBinding(var, valMap.get(var));
-			} else if (bs.getBindingNames().size() > 0
-					&& bs.getBinding(var) != null) {
-				bSet.addBinding(var, bs.getBinding(var).getValue());
-			}
-		}
-
-		return converter.convert(bSet, new VariableOrder(prefixVars));
-	}
-
-	/**
-	 *
-	 * @param key - Accumulo key obtained from scan
-	 * @param tableVarMap - map that associated query variables and table variables
-	 * @return - BindingSet without values associated with constant constraints
-	 * @throws BindingSetConversionException
-	 */
-	private static BindingSet getBindingSetWithoutConstants(Key key,
-			Map<String, String> tableVarMap) throws BindingSetConversionException {
-		final byte[] row = key.getRow().getBytes();
-		final String[] varOrder = key.getColumnFamily().toString()
-				.split(ExternalTupleSet.VAR_ORDER_DELIM);
-
-		BindingSet bindingSet = converter.convert(row, new VariableOrder(varOrder));
-		final QueryBindingSet temp = new QueryBindingSet(bindingSet);
-
-		final QueryBindingSet bs = new QueryBindingSet();
-		for (final String var : temp.getBindingNames()) {
-			if (!tableVarMap.get(var).startsWith(ExternalTupleSet.CONST_PREFIX)) {
-				bs.addBinding(tableVarMap.get(var), temp.getValue(var));
-			}
-		}
-		return bs;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/GeneralizedExternalProcessor.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/GeneralizedExternalProcessor.java b/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/GeneralizedExternalProcessor.java
index 58e84d9..08d52ed 100644
--- a/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/GeneralizedExternalProcessor.java
+++ b/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/GeneralizedExternalProcessor.java
@@ -28,8 +28,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import mvm.rya.indexing.external.QueryVariableNormalizer.VarCollector;
 import mvm.rya.indexing.external.tupleSet.ExternalTupleSet;
+import mvm.rya.indexing.pcj.matching.QueryVariableNormalizer.VarCollector;
 
 import org.openrdf.query.algebra.BindingSetAssignment;
 import org.openrdf.query.algebra.Filter;

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/IndexedExecutionPlanGenerator.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/IndexedExecutionPlanGenerator.java b/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/IndexedExecutionPlanGenerator.java
index a0fca34..22b1e85 100644
--- a/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/IndexedExecutionPlanGenerator.java
+++ b/extras/indexing/src/main/java/mvm/rya/indexing/IndexPlanValidator/IndexedExecutionPlanGenerator.java
@@ -24,8 +24,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
 
-import mvm.rya.indexing.external.QueryVariableNormalizer;
 import mvm.rya.indexing.external.tupleSet.ExternalTupleSet;
+import mvm.rya.indexing.pcj.matching.QueryVariableNormalizer;
 
 import org.openrdf.query.algebra.Projection;
 import org.openrdf.query.algebra.TupleExpr;
@@ -113,7 +113,6 @@ public class IndexedExecutionPlanGenerator implements ExternalIndexMatcher {
             try {
                 tupList = QueryVariableNormalizer.getNormalizedIndex(query, e.getTupleExpr());
             } catch (final Exception e1) {
-                // TODO Auto-generated catch block
                 e1.printStackTrace();
             }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/indexing/PcjQuery.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/PcjQuery.java b/extras/indexing/src/main/java/mvm/rya/indexing/PcjQuery.java
deleted file mode 100644
index 57f77cf..0000000
--- a/extras/indexing/src/main/java/mvm/rya/indexing/PcjQuery.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package mvm.rya.indexing;
-
-/*
- * 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 info.aduna.iteration.CloseableIteration;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.accumulo.core.client.TableNotFoundException;
-import org.openrdf.model.Value;
-import org.openrdf.query.BindingSet;
-import org.openrdf.query.QueryEvaluationException;
-
-public interface PcjQuery {
-
-    public abstract CloseableIteration<BindingSet, QueryEvaluationException> queryPrecompJoin(List<String> varOrder,
-            String localityGroup, Map<String, Value> valMap, Map<String, String> varMap, Collection<BindingSet> constraints) throws QueryEvaluationException,TableNotFoundException;
-
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/ConfigUtils.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/ConfigUtils.java b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/ConfigUtils.java
index 6c87182..1b92117 100644
--- a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/ConfigUtils.java
+++ b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/ConfigUtils.java
@@ -25,6 +25,20 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import mvm.rya.accumulo.AccumuloRdfConfiguration;
+import mvm.rya.api.RdfCloudTripleStoreConfiguration;
+import mvm.rya.indexing.FilterFunctionOptimizer;
+import mvm.rya.indexing.accumulo.entity.EntityCentricIndex;
+import mvm.rya.indexing.accumulo.entity.EntityOptimizer;
+import mvm.rya.indexing.accumulo.freetext.AccumuloFreeTextIndexer;
+import mvm.rya.indexing.accumulo.freetext.LuceneTokenizer;
+import mvm.rya.indexing.accumulo.freetext.Tokenizer;
+import mvm.rya.indexing.accumulo.geo.GeoMesaGeoIndexer;
+import mvm.rya.indexing.accumulo.temporal.AccumuloTemporalIndexer;
+import mvm.rya.indexing.mongodb.MongoFreeTextIndexer;
+import mvm.rya.indexing.mongodb.MongoGeoIndexer;
+import mvm.rya.indexing.pcj.matching.PCJOptimizer;
+
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.accumulo.core.client.BatchScanner;
@@ -49,20 +63,6 @@ import org.openrdf.model.impl.URIImpl;
 
 import com.google.common.collect.Lists;
 
-import mvm.rya.accumulo.AccumuloRdfConfiguration;
-import mvm.rya.api.RdfCloudTripleStoreConfiguration;
-import mvm.rya.indexing.FilterFunctionOptimizer;
-import mvm.rya.indexing.accumulo.entity.EntityCentricIndex;
-import mvm.rya.indexing.accumulo.entity.EntityOptimizer;
-import mvm.rya.indexing.accumulo.freetext.AccumuloFreeTextIndexer;
-import mvm.rya.indexing.accumulo.freetext.LuceneTokenizer;
-import mvm.rya.indexing.accumulo.freetext.Tokenizer;
-import mvm.rya.indexing.accumulo.geo.GeoMesaGeoIndexer;
-import mvm.rya.indexing.accumulo.temporal.AccumuloTemporalIndexer;
-import mvm.rya.indexing.external.PrecompJoinOptimizer;
-import mvm.rya.indexing.mongodb.MongoFreeTextIndexer;
-import mvm.rya.indexing.mongodb.MongoGeoIndexer;
-
 /**
  * A set of configuration utils to read a Hadoop {@link Configuration} object and create Cloudbase/Accumulo objects.
  */
@@ -157,7 +157,7 @@ public class ConfigUtils {
         return false;
     }
 
-    private static String getIndexTableName(final Configuration conf, final String indexTableNameConf, final String altSuffix){
+    private static String getIndexTableName(Configuration conf, String indexTableNameConf, String altSuffix){
         String value = conf.get(indexTableNameConf);
         if (value == null){
             final String defaultTableName = conf.get(RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX);
@@ -183,12 +183,12 @@ public class ConfigUtils {
         return getIndexTableName(conf, GEO_TABLENAME, "geo");
     }
 
-    public static String getTemporalTableName(final Configuration conf) {
+    public static String getTemporalTableName(Configuration conf) {
         return getIndexTableName(conf, TEMPORAL_TABLENAME, "temporal");
     }
 
 
-    public static String getEntityTableName(final Configuration conf) {
+    public static String getEntityTableName(Configuration conf) {
         return getIndexTableName(conf, ENTITY_TABLENAME, "entity");
     }
 
@@ -253,10 +253,11 @@ public class ConfigUtils {
 		final Connector connector = ConfigUtils.getConnector(conf);
 		final Authorizations auths = ConfigUtils.getAuthorizations(conf);
 		Integer numThreads = null;
-		if (conf instanceof RdfCloudTripleStoreConfiguration)
+		if (conf instanceof RdfCloudTripleStoreConfiguration) {
 			numThreads = ((RdfCloudTripleStoreConfiguration) conf).getNumThreads();
-		else
+		} else {
 			numThreads = conf.getInt(RdfCloudTripleStoreConfiguration.CONF_NUM_THREADS, 2);
+		}
 		return connector.createBatchScanner(tablename, auths, numThreads);
 	}
 
@@ -341,39 +342,39 @@ public class ConfigUtils {
         return conf.getInt(GEO_NUM_PARTITIONS, getNumPartitions(conf));
     }
 
-    public static boolean getUseGeo(final Configuration conf) {
+    public static boolean getUseGeo(Configuration conf) {
         return conf.getBoolean(USE_GEO, false);
     }
 
-    public static boolean getUseFreeText(final Configuration conf) {
+    public static boolean getUseFreeText(Configuration conf) {
         return conf.getBoolean(USE_FREETEXT, false);
     }
 
-    public static boolean getUseTemporal(final Configuration conf) {
+    public static boolean getUseTemporal(Configuration conf) {
         return conf.getBoolean(USE_TEMPORAL, false);
     }
 
-    public static boolean getUseEntity(final Configuration conf) {
+    public static boolean getUseEntity(Configuration conf) {
         return conf.getBoolean(USE_ENTITY, false);
     }
 
-    public static boolean getUsePCJ(final Configuration conf) {
+    public static boolean getUsePCJ(Configuration conf) {
         return conf.getBoolean(USE_PCJ, false);
     }
 
-    public static boolean getUseOptimalPCJ(final Configuration conf) {
+    public static boolean getUseOptimalPCJ(Configuration conf) {
         return conf.getBoolean(USE_OPTIMAL_PCJ, false);
     }
 
-    public static boolean getUseMongo(final Configuration conf) {
+    public static boolean getUseMongo(Configuration conf) {
         return conf.getBoolean(USE_MONGO, false);
     }
 
 
-    public static void setIndexers(final RdfCloudTripleStoreConfiguration conf) {
+    public static void setIndexers(RdfCloudTripleStoreConfiguration conf) {
 
-        final List<String> indexList = Lists.newArrayList();
-        final List<String> optimizers = Lists.newArrayList();
+        List<String> indexList = Lists.newArrayList();
+        List<String> optimizers = Lists.newArrayList();
 
         boolean useFilterIndex = false;
 
@@ -389,7 +390,7 @@ public class ConfigUtils {
         } else {
 
             if (getUsePCJ(conf) || getUseOptimalPCJ(conf)) {
-                conf.setPcjOptimizer(PrecompJoinOptimizer.class);
+                conf.setPcjOptimizer(PCJOptimizer.class);
             }
 
             if (getUseGeo(conf)) {
@@ -421,5 +422,9 @@ public class ConfigUtils {
 
         conf.setStrings(AccumuloRdfConfiguration.CONF_ADDITIONAL_INDEXERS, indexList.toArray(new String[]{}));
         conf.setStrings(AccumuloRdfConfiguration.CONF_OPTIMIZERS, optimizers.toArray(new String[]{}));
+
     }
-}
\ No newline at end of file
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/96dd55ec/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/entity/AccumuloDocIdIndexer.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/entity/AccumuloDocIdIndexer.java b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/entity/AccumuloDocIdIndexer.java
index feb894f..73378cf 100644
--- a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/entity/AccumuloDocIdIndexer.java
+++ b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/entity/AccumuloDocIdIndexer.java
@@ -8,9 +8,9 @@ package mvm.rya.indexing.accumulo.entity;
  * 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
@@ -56,7 +56,6 @@ import org.apache.accumulo.core.data.Key;
 import org.apache.accumulo.core.data.Range;
 import org.apache.accumulo.core.data.Value;
 import org.apache.accumulo.core.security.Authorizations;
-import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.io.Text;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.MalformedQueryException;
@@ -75,23 +74,23 @@ import com.google.common.primitives.Bytes;
 
 public class AccumuloDocIdIndexer implements DocIdIndexer {
 
-    
-    
+
+
     private BatchScanner bs;
     private AccumuloRdfConfiguration conf;
- 
+
     public AccumuloDocIdIndexer(RdfCloudTripleStoreConfiguration conf) throws AccumuloException, AccumuloSecurityException {
         Preconditions.checkArgument(conf instanceof RdfCloudTripleStoreConfiguration, "conf must be isntance of RdfCloudTripleStoreConfiguration");
         this.conf = (AccumuloRdfConfiguration) conf;
-        //Connector conn = ConfigUtils.getConnector(conf);  
+        //Connector conn = ConfigUtils.getConnector(conf);
     }
-    
-    
-    
-    
+
+
+
+
     public CloseableIteration<BindingSet, QueryEvaluationException> queryDocIndex(String sparqlQuery,
             Collection<BindingSet> constraints) throws TableNotFoundException, QueryEvaluationException {
-    
+
         SPARQLParser parser = new SPARQLParser();
         ParsedQuery pq1 = null;
         try {
@@ -99,22 +98,22 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
         } catch (MalformedQueryException e) {
             e.printStackTrace();
         }
-        
+
         TupleExpr te1 = pq1.getTupleExpr();
         List<StatementPattern> spList1 = StatementPatternCollector.process(te1);
-        
+
         if(StarQuery.isValidStarQuery(spList1)) {
             StarQuery sq1 = new StarQuery(spList1);
             return queryDocIndex(sq1, constraints);
         } else {
             throw new IllegalArgumentException("Invalid star query!");
         }
-   
+
     }
-    
-    
-    
-    
+
+
+
+
     @Override
     public CloseableIteration<BindingSet, QueryEvaluationException> queryDocIndex(StarQuery query,
             Collection<BindingSet> constraints) throws TableNotFoundException, QueryEvaluationException {
@@ -132,50 +131,50 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
             commonVarNames = Sets.newHashSet();
             unCommonVarNames = Sets.newHashSet();
         }
-        
+
         if( commonVarNames.size() == 1 && !query.commonVarConstant() && commonVarNames.contains(query.getCommonVarName())) {
-            
+
             final HashMultimap<String, BindingSet> map = HashMultimap.create();
             final String commonVar = starQ.getCommonVarName();
             final Iterator<Entry<Key, Value>> intersections;
             final BatchScanner scan;
             Set<Range> ranges = Sets.newHashSet();
-            
+
             while(bs.hasNext()) {
-                
+
                 BindingSet currentBs = bs.next();
-                
+
                 if(currentBs.getBinding(commonVar) == null) {
                     continue;
                 }
-                
+
                 String row = currentBs.getBinding(commonVar).getValue().stringValue();
-                ranges.add(new Range(row)); 
+                ranges.add(new Range(row));
                 map.put(row, currentBs);
-                              
+
             }
             scan = runQuery(starQ, ranges);
             intersections = scan.iterator();
-            
-            
+
+
             return new CloseableIteration<BindingSet, QueryEvaluationException>() {
 
-                
+
                 private QueryBindingSet currentSolutionBs = null;
                 private boolean hasNextCalled = false;
                 private boolean isEmpty = false;
-                private Iterator<BindingSet> inputSet = (new ArrayList<BindingSet>()).iterator();
+                private Iterator<BindingSet> inputSet = new ArrayList<BindingSet>().iterator();
                 private BindingSet currentBs;
                 private Key key;
-                
-                
-                
+
+
+
                 @Override
                 public boolean hasNext() throws QueryEvaluationException {
                     if (!hasNextCalled && !isEmpty) {
                         while (inputSet.hasNext() || intersections.hasNext()) {
                             if (!inputSet.hasNext()) {
-                                key = intersections.next().getKey();   
+                                key = intersections.next().getKey();
                                 inputSet = map.get(key.getRow().toString()).iterator();
                             }
                             currentBs = inputSet.next();
@@ -199,7 +198,7 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
 
                 }
 
-             
+
                 @Override
                 public BindingSet next() throws QueryEvaluationException {
 
@@ -227,10 +226,10 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
                 public void close() throws QueryEvaluationException {
                     scan.close();
                 }
-                
+
             };
-            
-            
+
+
         } else {
 
             return new CloseableIteration<BindingSet, QueryEvaluationException>() {
@@ -249,7 +248,7 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
                 private StarQuery sq = new StarQuery(starQ);
                 private Set<Range> emptyRangeSet = Sets.newHashSet();
                 private BatchScanner scan;
-                
+
                 @Override
                 public BindingSet next() throws QueryEvaluationException {
                     if (hasNextCalled) {
@@ -268,7 +267,7 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
 
                 @Override
                 public boolean hasNext() throws QueryEvaluationException {
-                    
+
                     if (!init) {
                         if (intersections == null && bs.hasNext()) {
                             currentBs = bs.next();
@@ -300,7 +299,7 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
                             } else {
                                 continue;
                             }
-                           
+
                             if (sq.commonVarConstant() && currentSolutionBs.size() == unCommonVarNames.size() + sq.getUnCommonVars().size()) {
                                 hasNextCalled = true;
                                 return true;
@@ -327,21 +326,21 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
             };
         }
     }
-    
+
     private QueryBindingSet deserializeKey(Key key, StarQuery sq, BindingSet currentBs, Set<String> unCommonVar) {
-        
-        
+
+
         QueryBindingSet currentSolutionBs = new QueryBindingSet();
-        
+
         Text row = key.getRow();
         Text cq = key.getColumnQualifier();
-        
-        
+
+
         String[] cqArray = cq.toString().split(DocIndexIteratorUtil.DOC_ID_INDEX_DELIM);
 
         boolean commonVarSet = false;
-        
-        //if common Var is constant there is no common variable to assign a value to 
+
+        //if common Var is constant there is no common variable to assign a value to
         if(sq.commonVarConstant()) {
             commonVarSet = true;
         }
@@ -363,7 +362,7 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
             byte[] cqContent = Arrays.copyOfRange(cqBytes, secondIndex + 1, typeIndex);
             byte[] objType = Arrays.copyOfRange(cqBytes, typeIndex, cqBytes.length);
 
-            if ((new String(tripleComponent)).equals("object")) {
+            if (new String(tripleComponent).equals("object")) {
                 byte[] object = Bytes.concat(cqContent, objType);
                 org.openrdf.model.Value v = null;
                 try {
@@ -374,7 +373,7 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
                 }
                 currentSolutionBs.addBinding(s, v);
 
-            } else if ((new String(tripleComponent)).equals("subject")) {
+            } else if (new String(tripleComponent).equals("subject")) {
                 if (!commonVarSet) {
                     byte[] object = Bytes.concat(row.getBytes(), objType);
                     org.openrdf.model.Value v = null;
@@ -398,9 +397,9 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
         }
         return currentSolutionBs;
     }
-    
+
    private BatchScanner runQuery(StarQuery query, Collection<Range> ranges) throws QueryEvaluationException {
-       
+
     try {
             if (ranges.size() == 0) {
                 String rangeText = query.getCommonVarValue();
@@ -411,13 +410,13 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
                     r = new Range();
                 }
                 ranges = Collections.singleton(r);
-            } 
-        
+            }
+
         Connector accCon = ConfigUtils.getConnector(conf);
         IteratorSetting is = new IteratorSetting(30, "fii", DocumentIndexIntersectingIterator.class);
 
         DocumentIndexIntersectingIterator.setColumnFamilies(is, query.getColumnCond());
-        
+
         if(query.hasContext()) {
             DocumentIndexIntersectingIterator.setContext(is, query.getContextURI());
         }
@@ -425,9 +424,9 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
                 new Authorizations(conf.get(ConfigUtils.CLOUDBASE_AUTHS)), 15);
         bs.addScanIterator(is);
         bs.setRanges(ranges);
-        
+
         return bs;
-    
+
     } catch (TableNotFoundException e) {
         e.printStackTrace();
     } catch (AccumuloException e) {
@@ -437,7 +436,7 @@ public class AccumuloDocIdIndexer implements DocIdIndexer {
     }
         throw new QueryEvaluationException();
    }
-    
+
 
     @Override
     public void close() throws IOException {