You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rya.apache.org by ca...@apache.org on 2018/01/12 21:25:29 UTC

[1/8] incubator-rya git commit: RYA-303 Mongo PCJ Support. Closes #172.

Repository: incubator-rya
Updated Branches:
  refs/heads/master 9f611019f -> c826ffea4


http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java b/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java
index d8d5b8f..75eb0d4 100644
--- a/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java
+++ b/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java
@@ -84,7 +84,7 @@ public class RyaAdminCommandsTest {
         when(mockCreatePCJ.createPCJ( eq(instanceName), eq(sparql), eq(strategies) ) ).thenReturn( pcjId );
 
         final RyaClient mockCommands = mock(RyaClient.class);
-        when(mockCommands.getCreatePCJ()).thenReturn( java.util.Optional.of(mockCreatePCJ) );
+        when(mockCommands.getCreatePCJ()).thenReturn(mockCreatePCJ);
 
         final SharedShellState state = new SharedShellState();
         state.connectedToAccumulo(mock(AccumuloConnectionDetails.class), mockCommands);
@@ -153,7 +153,7 @@ public class RyaAdminCommandsTest {
         final DeletePCJ mockDeletePCJ = mock(DeletePCJ.class);
 
         final RyaClient mockCommands = mock(RyaClient.class);
-        when(mockCommands.getDeletePCJ()).thenReturn( java.util.Optional.of(mockDeletePCJ) );
+        when(mockCommands.getDeletePCJ()).thenReturn(mockDeletePCJ);
 
         final SharedShellState state = new SharedShellState();
         state.connectedToAccumulo(mock(AccumuloConnectionDetails.class), mockCommands);
@@ -251,22 +251,22 @@ public class RyaAdminCommandsTest {
                 .addUser("bob")
                 .addUser("charlie")
                 .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
-              //RYA-215.setGeoIndexDetails( new GeoIndexDetails(true) )
+                //RYA-215.setGeoIndexDetails( new GeoIndexDetails(true) )
                 .setTemporalIndexDetails( new TemporalIndexDetails(true) )
                 .setFreeTextDetails( new FreeTextIndexDetails(true) )
                 .setPCJIndexDetails(
                         PCJIndexDetails.builder()
-                            .setEnabled(true)
-                            .setFluoDetails( new FluoDetails("test_instance_rya_pcj_updater") )
-                            .addPCJDetails(
-                                    PCJDetails.builder()
-                                        .setId("pcj 1")
-                                        .setUpdateStrategy(PCJUpdateStrategy.BATCH)
-                                        .setLastUpdateTime( new Date(1252521351L) ))
-                            .addPCJDetails(
-                                    PCJDetails.builder()
-                                        .setId("pcj 2")
-                                        .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL)))
+                        .setEnabled(true)
+                        .setFluoDetails( new FluoDetails("test_instance_rya_pcj_updater") )
+                        .addPCJDetails(
+                                PCJDetails.builder()
+                                .setId("pcj 1")
+                                .setUpdateStrategy(PCJUpdateStrategy.BATCH)
+                                .setLastUpdateTime( new Date(1252521351L) ))
+                        .addPCJDetails(
+                                PCJDetails.builder()
+                                .setId("pcj 2")
+                                .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL)))
                 .setProspectorDetails( new ProspectorDetails(Optional.of(new Date(12525211L))) )
                 .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date(125221351L))) )
                 .build();
@@ -290,33 +290,33 @@ public class RyaAdminCommandsTest {
         // Verify a message is returned that includes the details.
         final String expected =
                 "General Metadata:\n" +
-                "  Instance Name: test_instance\n" +
-                "  RYA Version: 1.2.3.4\n" +
-                "  Users: alice, bob, charlie\n" +
-                "Secondary Indicies:\n" +
-                "  Entity Centric Index:\n" +
-                "    Enabled: true\n" +
-              //RYA-215"  Geospatial Index:\n" +
-            //RYA-215"    Enabled: true\n" +
-                "  Free Text Index:\n" +
-                "    Enabled: true\n" +
-                "  Temporal Index:\n" +
-                "    Enabled: true\n" +
-                "  PCJ Index:\n" +
-                "    Enabled: true\n" +
-                "    Fluo App Name: test_instance_rya_pcj_updater\n" +
-                "    PCJs:\n" +
-                "      ID: pcj 1\n" +
-                "        Update Strategy: BATCH\n" +
-                "        Last Update Time: Thu Jan 15 06:55:21 EST 1970\n" +
-                "      ID: pcj 2\n" +
-                "        Update Strategy: INCREMENTAL\n" +
-                "        Last Update Time: unavailable\n" +
-                "Statistics:\n" +
-                "  Prospector:\n" +
-                "    Last Update Time: Wed Dec 31 22:28:45 EST 1969\n" +
-                "  Join Selectivity:\n" +
-                "    Last Updated Time: Fri Jan 02 05:47:01 EST 1970\n";
+                        "  Instance Name: test_instance\n" +
+                        "  RYA Version: 1.2.3.4\n" +
+                        "  Users: alice, bob, charlie\n" +
+                        "Secondary Indicies:\n" +
+                        "  Entity Centric Index:\n" +
+                        "    Enabled: true\n" +
+                        //RYA-215"  Geospatial Index:\n" +
+                        //RYA-215"    Enabled: true\n" +
+                        "  Free Text Index:\n" +
+                        "    Enabled: true\n" +
+                        "  Temporal Index:\n" +
+                        "    Enabled: true\n" +
+                        "  PCJ Index:\n" +
+                        "    Enabled: true\n" +
+                        "    Fluo App Name: test_instance_rya_pcj_updater\n" +
+                        "    PCJs:\n" +
+                        "      ID: pcj 1\n" +
+                        "        Update Strategy: BATCH\n" +
+                        "        Last Update Time: Thu Jan 15 06:55:21 EST 1970\n" +
+                        "      ID: pcj 2\n" +
+                        "        Update Strategy: INCREMENTAL\n" +
+                        "        Last Update Time: unavailable\n" +
+                        "Statistics:\n" +
+                        "  Prospector:\n" +
+                        "    Last Update Time: Wed Dec 31 22:28:45 EST 1969\n" +
+                        "  Join Selectivity:\n" +
+                        "    Last Updated Time: Fri Jan 02 05:47:01 EST 1970\n";
         assertEquals(expected, message);
     }
 
@@ -455,11 +455,13 @@ public class RyaAdminCommandsTest {
         final String instanceName = "unitTests";
         final boolean enableFreeTextIndex = false;
         final boolean enableTemporalIndex = false;
+        final boolean enablePcjIndex = false;
 
         // Execute the command.
         final InstallConfiguration installConfig = InstallConfiguration.builder()
                 .setEnableFreeTextIndex(enableFreeTextIndex)
                 .setEnableTemporalIndex(enableTemporalIndex)
+                .setEnablePcjIndex(enablePcjIndex)
                 .build();
 
         final InstallPrompt mockInstallPrompt = mock(InstallPrompt.class);
@@ -468,7 +470,7 @@ public class RyaAdminCommandsTest {
         when(mockInstallPrompt.promptVerified(eq(instanceName), eq(installConfig))).thenReturn(true);
 
         final RyaAdminCommands commands = new RyaAdminCommands(state, mockInstallPrompt, mock(SparqlPrompt.class), mock(UninstallPrompt.class));
-        final String message = commands.installWithMongoParameters(instanceName, enableFreeTextIndex, enableTemporalIndex);
+        final String message = commands.installWithMongoParameters(instanceName, enableFreeTextIndex, enableTemporalIndex, enablePcjIndex);
 
         // Verify the values that were provided to the command were passed through to the Install.
         verify(mockInstall).install(eq(instanceName), eq(installConfig));
@@ -499,10 +501,10 @@ public class RyaAdminCommandsTest {
         // Verify a message is returned that lists the the instances.
         final String expected =
                 "Rya instance names:\n" +
-                "   a\n" +
-                " * b\n" +
-                "   c\n" +
-                "   d\n";
+                        "   a\n" +
+                        " * b\n" +
+                        "   c\n" +
+                        "   d\n";
         assertEquals(expected, message);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/shell/src/test/java/org/apache/rya/shell/util/RyaDetailsFormatterTest.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/test/java/org/apache/rya/shell/util/RyaDetailsFormatterTest.java b/extras/shell/src/test/java/org/apache/rya/shell/util/RyaDetailsFormatterTest.java
index e11b50f..4d4fd9b 100644
--- a/extras/shell/src/test/java/org/apache/rya/shell/util/RyaDetailsFormatterTest.java
+++ b/extras/shell/src/test/java/org/apache/rya/shell/util/RyaDetailsFormatterTest.java
@@ -121,7 +121,7 @@ public class RyaDetailsFormatterTest {
           //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
             .setTemporalIndexDetails( new TemporalIndexDetails(true) )
             .setFreeTextDetails( new FreeTextIndexDetails(true) )
-            .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(false))
+            .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(true))
             .setProspectorDetails( new ProspectorDetails(Optional.absent()) )
             .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.absent()) )
             .build();
@@ -139,7 +139,11 @@ public class RyaDetailsFormatterTest {
                 "  Free Text Index:\n" +
                 "    Enabled: true\n" +
                 "  Temporal Index:\n" +
-                "    Enabled: true\n";
+                "    Enabled: true\n" +
+                "  PCJ Index:\n" +
+                "    Enabled: true\n" +
+                "    PCJs:\n" +
+                "      No PCJs have been added yet.\n";
 
         assertEquals(expected, formatted);
     }


[5/8] incubator-rya git commit: RYA-303 Mongo PCJ Support. Closes #172.

Posted by ca...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/external/PcjIntegrationTestingUtil.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PcjIntegrationTestingUtil.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PcjIntegrationTestingUtil.java
index f8d841b..8b3b8f5 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PcjIntegrationTestingUtil.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PcjIntegrationTestingUtil.java
@@ -1,6 +1,4 @@
-package org.apache.rya.indexing.external;
-
-/*
+/**
  * 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
@@ -18,10 +16,12 @@ package org.apache.rya.indexing.external;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.rya.indexing.external;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.net.UnknownHostException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
@@ -35,6 +35,12 @@ import org.apache.accumulo.core.client.MutationsRejectedException;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.admin.TableOperations;
 import org.apache.accumulo.core.data.Mutation;
+import org.apache.rya.accumulo.AccumuloRdfConfiguration;
+import org.apache.rya.api.model.VisibilityBindingSet;
+import org.apache.rya.api.persist.RyaDAOException;
+import org.apache.rya.indexing.accumulo.ConfigUtils;
+import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.rya.indexing.pcj.storage.PcjException;
 import org.apache.rya.indexing.pcj.storage.PcjMetadata;
 import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjSerializer;
@@ -43,6 +49,9 @@ import org.apache.rya.indexing.pcj.storage.accumulo.PcjTables;
 import org.apache.rya.indexing.pcj.storage.accumulo.PcjVarOrderFactory;
 import org.apache.rya.indexing.pcj.storage.accumulo.ShiftVarOrderFactory;
 import org.apache.rya.indexing.pcj.storage.accumulo.VariableOrder;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjDocuments;
+import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
+import org.apache.rya.sail.config.RyaSailFactory;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.MalformedQueryException;
 import org.openrdf.query.QueryEvaluationException;
@@ -62,14 +71,7 @@ import org.openrdf.sail.SailException;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.Sets;
-
-import org.apache.rya.accumulo.AccumuloRdfConfiguration;
-import org.apache.rya.api.persist.RyaDAOException;
-import org.apache.rya.indexing.accumulo.ConfigUtils;
-import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType;
-import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
-import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
-import org.apache.rya.sail.config.RyaSailFactory;
+import com.mongodb.MongoClient;
 
 public class PcjIntegrationTestingUtil {
 
@@ -96,7 +98,7 @@ public class PcjIntegrationTestingUtil {
         }
     }
 
-    public static SailRepository getPcjRepo(final String tablePrefix, final String instance)
+    public static SailRepository getAccumuloPcjRepo(final String tablePrefix, final String instance)
             throws AccumuloException, AccumuloSecurityException,
             RyaDAOException, RepositoryException, InferenceEngineException,
             NumberFormatException, UnknownHostException, SailException {
@@ -104,26 +106,26 @@ public class PcjIntegrationTestingUtil {
         final AccumuloRdfConfiguration pcjConf = new AccumuloRdfConfiguration();
         pcjConf.set(ConfigUtils.USE_PCJ, "true");
         pcjConf.set(PrecomputedJoinIndexerConfig.PCJ_STORAGE_TYPE,PrecomputedJoinStorageType.ACCUMULO.name());
-        populateTestConfig(instance, tablePrefix, pcjConf);
+        populateAccumuloConfig(instance, tablePrefix, pcjConf);
 
         final Sail pcjSail = RyaSailFactory.getInstance(pcjConf);
         final SailRepository pcjRepo = new SailRepository(pcjSail);
         return pcjRepo;
     }
 
-    public static SailRepository getNonPcjRepo(final String tablePrefix,
+    public static SailRepository getAccumuloNonPcjRepo(final String tablePrefix,
             final String instance) throws AccumuloException,
-            AccumuloSecurityException, RyaDAOException, RepositoryException, InferenceEngineException,
-            NumberFormatException, UnknownHostException, SailException {
+    AccumuloSecurityException, RyaDAOException, RepositoryException, InferenceEngineException,
+    NumberFormatException, UnknownHostException, SailException {
 
         final AccumuloRdfConfiguration nonPcjConf = new AccumuloRdfConfiguration();
-        populateTestConfig(instance, tablePrefix, nonPcjConf);
+        populateAccumuloConfig(instance, tablePrefix, nonPcjConf);
         final Sail nonPcjSail = RyaSailFactory.getInstance(nonPcjConf);
         final SailRepository nonPcjRepo = new SailRepository(nonPcjSail);
         return nonPcjRepo;
     }
 
-    private static void populateTestConfig(final String instance, final String tablePrefix, final AccumuloRdfConfiguration config) {
+    private static void populateAccumuloConfig(final String instance, final String tablePrefix, final AccumuloRdfConfiguration config) {
         config.set(ConfigUtils.USE_MOCK_INSTANCE, "true");
         config.set(ConfigUtils.CLOUDBASE_INSTANCE, instance);
         config.set(ConfigUtils.CLOUDBASE_USER, "test_user");
@@ -138,9 +140,13 @@ public class PcjIntegrationTestingUtil {
         repo.shutDown();
     }
 
+    public static void deleteIndexDocuments(final MongoClient client, final String instance) {
+        client.getDatabase(instance).getCollection(MongoPcjDocuments.PCJ_COLLECTION_NAME).drop();
+    }
+
     public static void deleteIndexTables(final Connector accCon, final int tableNum,
             final String prefix) throws AccumuloException, AccumuloSecurityException,
-            TableNotFoundException {
+    TableNotFoundException {
         final TableOperations ops = accCon.tableOperations();
         final String tablename = prefix + "INDEX_";
         for (int i = 1; i < tableNum + 1; i++) {
@@ -151,7 +157,7 @@ public class PcjIntegrationTestingUtil {
     }
 
     public static class BindingSetAssignmentCollector extends
-            QueryModelVisitorBase<RuntimeException> {
+    QueryModelVisitorBase<RuntimeException> {
 
         private final Set<QueryModelNode> bindingSetList = Sets.newHashSet();
 
@@ -172,7 +178,7 @@ public class PcjIntegrationTestingUtil {
     }
 
     public static class ExternalTupleVisitor extends
-            QueryModelVisitorBase<RuntimeException> {
+    QueryModelVisitorBase<RuntimeException> {
 
         private final Set<QueryModelNode> eSet = new HashSet<>();
 
@@ -195,13 +201,13 @@ public class PcjIntegrationTestingUtil {
 
 
 
-//****************************Creation and Population of PcjTables***********************************
+    //****************************Creation and Population of PcjTables Accumulo***************************
 
 
 
 
 
-      /**
+    /**
      * Creates a new PCJ Table in Accumulo and populates it by scanning an
      * instance of Rya for historic matches.
      * <p>
@@ -268,7 +274,7 @@ public class PcjIntegrationTestingUtil {
      */
     public static void populatePcj(final Connector accumuloConn,
             final String pcjTableName, final RepositoryConnection ryaConn)
-            throws PcjException {
+                    throws PcjException {
         checkNotNull(accumuloConn);
         checkNotNull(pcjTableName);
         checkNotNull(ryaConn);
@@ -309,7 +315,7 @@ public class PcjIntegrationTestingUtil {
 
     public static void addResults(final Connector accumuloConn,
             final String pcjTableName, final Collection<BindingSet> results)
-            throws PcjException {
+                    throws PcjException {
         checkNotNull(accumuloConn);
         checkNotNull(pcjTableName);
         checkNotNull(results);
@@ -336,7 +342,7 @@ public class PcjIntegrationTestingUtil {
      */
     private static void writeResults(final Connector accumuloConn,
             final String pcjTableName, final Collection<BindingSet> results)
-            throws PcjException {
+                    throws PcjException {
         checkNotNull(accumuloConn);
         checkNotNull(pcjTableName);
         checkNotNull(results);
@@ -387,7 +393,7 @@ public class PcjIntegrationTestingUtil {
      */
     private static Set<Mutation> makeWriteResultMutations(
             final Set<VariableOrder> varOrders, final BindingSet result)
-            throws PcjException {
+                    throws PcjException {
         checkNotNull(varOrders);
         checkNotNull(result);
 
@@ -410,4 +416,112 @@ public class PcjIntegrationTestingUtil {
 
         return mutations;
     }
+
+    //****************************Creation and Population of PcjTables Mongo ***********************************
+
+    public static void deleteCoreRyaTables(final MongoClient client, final String instance, final String collName) {
+        final boolean bool = client.isLocked();
+        client.getDatabase(instance).getCollection(collName).drop();
+    }
+
+    /**
+     * Creates a new PCJ Table in Accumulo and populates it by scanning an
+     * instance of Rya for historic matches.
+     * <p>
+     * If any portion of this operation fails along the way, the partially
+     * create PCJ table will be left in Accumulo.
+     *
+     * @param ryaConn - Connects to the Rya that will be scanned. (not null)
+     * @param mongoClient - Connects to the mongoDB that hosts the PCJ results. (not null)
+     * @param pcjName - The name of the PCJ table that will be created. (not null)
+     * @param sparql - The SPARQL query whose results will be loaded into the table. (not null)
+     * @throws PcjException The PCJ table could not be create or the values from Rya were
+     *         not able to be loaded into it.
+     */
+    public static void createAndPopulatePcj(final RepositoryConnection ryaConn, final MongoClient mongoClient, final String pcjName, final String instanceName, final String sparql) throws PcjException {
+        checkNotNull(ryaConn);
+        checkNotNull(mongoClient);
+        checkNotNull(pcjName);
+        checkNotNull(instanceName);
+        checkNotNull(sparql);
+
+        final MongoPcjDocuments pcj = new MongoPcjDocuments(mongoClient, instanceName);
+
+        pcj.createPcj(pcjName, sparql);
+
+        // Load historic matches from Rya into the PCJ table.
+        populatePcj(pcj, pcjName, ryaConn);
+    }
+
+
+    /**
+     * Scan Rya for results that solve the PCJ's query and store them in the PCJ
+     * table.
+     * <p>
+     * This method assumes the PCJ table has already been created.
+     *
+     * @param mongoClient - A connection to the mongoDB that hosts the PCJ table. (not null)
+     * @param pcjTableName - The name of the PCJ table that will receive the results. (not null)
+     * @param ryaConn - A connection to the Rya store that will be queried to find results. (not null)
+     * @throws PcjException
+     *             If results could not be written to the PCJ table, the PCJ
+     *             table does not exist, or the query that is being execute was
+     *             malformed.
+     */
+    public static void populatePcj(final MongoPcjDocuments pcj, final String pcjTableName, final RepositoryConnection ryaConn) throws PcjException {
+        checkNotNull(pcj);
+        checkNotNull(pcjTableName);
+        checkNotNull(ryaConn);
+
+        try {
+            // Fetch the query that needs to be executed from the PCJ table.
+            final PcjMetadata pcjMetadata = pcj.getPcjMetadata(pcjTableName);
+            final String sparql = pcjMetadata.getSparql();
+
+            // Query Rya for results to the SPARQL query.
+            final TupleQuery query = ryaConn.prepareTupleQuery(QueryLanguage.SPARQL, sparql);
+            final TupleQueryResult results = query.evaluate();
+
+            // Load batches of 1000 of them at a time into the PCJ table
+            final Set<BindingSet> batch = new HashSet<>(1000);
+            while (results.hasNext()) {
+                batch.add(results.next());
+
+                if (batch.size() == 1000) {
+                    writeResults(pcj, pcjTableName, batch);
+                    batch.clear();
+                }
+            }
+
+            if (!batch.isEmpty()) {
+                writeResults(pcj, pcjTableName, batch);
+            }
+
+        } catch (RepositoryException | MalformedQueryException | QueryEvaluationException e) {
+            throw new PcjException("Could not populate a PCJ table with Rya results for the table named: " + pcjTableName, e);
+        }
+    }
+
+    /**
+     * Add a collection of results to a specific PCJ table.
+     *
+     * @param accumuloConn - A connection to the Accumulo that hosts the PCJ table. (not null)
+     * @param pcjTableName - The name of the PCJ table that will receive the results. (not null)
+     * @param results - Binding sets that will be written to the PCJ table. (not null)
+     * @throws PcjException The provided PCJ table doesn't exist, is missing the
+     *   PCJ metadata, or the result could not be written to it.
+     */
+    private static void writeResults(final MongoPcjDocuments pcj,
+            final String pcjTableName, final Collection<BindingSet> results)
+                    throws PcjException {
+        checkNotNull(pcj);
+        checkNotNull(pcjTableName);
+        checkNotNull(results);
+
+        final Collection<VisibilityBindingSet> visRes = new ArrayList<>();
+        results.forEach(bindingSet -> {
+            visRes.add(new VisibilityBindingSet(bindingSet));
+        });
+        pcj.addResults(pcjTableName, visRes);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerIT.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerIT.java
index c133a4a..86e5a8e 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerIT.java
@@ -74,10 +74,10 @@ public class PrecompJoinOptimizerIT {
 			TableNotFoundException, InferenceEngineException, NumberFormatException,
 			UnknownHostException, SailException {
 
-		repo = PcjIntegrationTestingUtil.getNonPcjRepo(tablePrefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloNonPcjRepo(tablePrefix, "instance");
 		conn = repo.getConnection();
 
-		pcjRepo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+		pcjRepo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
 		pcjConn = pcjRepo.getConnection();
 
 		sub = new URIImpl("uri:entity");
@@ -142,7 +142,7 @@ public class PrecompJoinOptimizerIT {
 		final CountingResultHandler crh = new CountingResultHandler();
 		PcjIntegrationTestingUtil.deleteCoreRyaTables(accCon, tablePrefix);
 		PcjIntegrationTestingUtil.closeAndShutdown(conn, repo);
-		repo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
 		conn = repo.getConnection();
 		conn.add(sub, talksTo, obj);
 		conn.add(sub2, talksTo, obj2);
@@ -231,7 +231,7 @@ public class PrecompJoinOptimizerIT {
 		final CountingResultHandler crh = new CountingResultHandler();
 		PcjIntegrationTestingUtil.deleteCoreRyaTables(accCon, tablePrefix);
 		PcjIntegrationTestingUtil.closeAndShutdown(conn, repo);
-		repo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
 		conn = repo.getConnection();
 		conn.add(sub, talksTo, obj);
 		conn.add(sub2, talksTo, obj2);
@@ -274,7 +274,7 @@ public class PrecompJoinOptimizerIT {
 		final CountingResultHandler crh = new CountingResultHandler();
 		PcjIntegrationTestingUtil.deleteCoreRyaTables(accCon, tablePrefix);
 		PcjIntegrationTestingUtil.closeAndShutdown(conn, repo);
-		repo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
 		conn = repo.getConnection();
 		conn.add(sub, talksTo, obj);
 		conn.add(sub2, talksTo, obj2);
@@ -321,7 +321,7 @@ public class PrecompJoinOptimizerIT {
 		final CountingResultHandler crh = new CountingResultHandler();
 		PcjIntegrationTestingUtil.deleteCoreRyaTables(accCon, tablePrefix);
 		PcjIntegrationTestingUtil.closeAndShutdown(conn, repo);
-		repo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
 		conn = repo.getConnection();
 		conn.add(sub, talksTo, obj);
 		conn.add(sub, RDFS.LABEL, new LiteralImpl("label"));
@@ -379,7 +379,7 @@ public class PrecompJoinOptimizerIT {
 
 		PcjIntegrationTestingUtil.deleteCoreRyaTables(accCon, tablePrefix);
 		PcjIntegrationTestingUtil.closeAndShutdown(conn, repo);
-		repo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
 		conn = repo.getConnection();
 		conn.add(sub2, RDF.TYPE, subclass2);
 		conn.add(sub2, RDF.TYPE, obj2);
@@ -445,7 +445,7 @@ public class PrecompJoinOptimizerIT {
 
 		PcjIntegrationTestingUtil.deleteCoreRyaTables(accCon, tablePrefix);
 		PcjIntegrationTestingUtil.closeAndShutdown(conn, repo);
-		repo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
 		conn = repo.getConnection();
 		conn.add(sub2, livesIn, city3);
 		conn.add(sub, livesIn, city3);

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest.java
index 7c806f9..0035898 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest.java
@@ -1,6 +1,4 @@
-package org.apache.rya.indexing.external;
-
-/*
+/**
  * 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
@@ -18,14 +16,28 @@ package org.apache.rya.indexing.external;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.rya.indexing.external;
+
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.hadoop.conf.Configuration;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
+import org.apache.rya.indexing.mongodb.pcj.MongoPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
+import org.apache.rya.indexing.pcj.matching.provider.AbstractPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
+import org.apache.rya.mongodb.EmbeddedMongoSingleton;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
 import org.junit.Assert;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 import org.openrdf.query.algebra.Projection;
 import org.openrdf.query.algebra.QueryModelNode;
 import org.openrdf.query.algebra.StatementPattern;
@@ -38,392 +50,406 @@ import org.openrdf.query.parser.sparql.SPARQLParser;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
-import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
-import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
-import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
-
+@RunWith(Parameterized.class)
 public class PrecompJoinOptimizerTest {
+    private final AbstractPcjIndexSetProvider provider;
+
+    @Parameterized.Parameters
+    public static Collection providers() throws Exception {
+        final StatefulMongoDBRdfConfiguration conf = new StatefulMongoDBRdfConfiguration(new Configuration(), EmbeddedMongoSingleton.getNewMongoClient());
+        return Lists.<AbstractPcjIndexSetProvider> newArrayList(
+                new AccumuloIndexSetProvider(new Configuration()),
+                new MongoPcjIndexSetProvider(conf)
+                );
+    }
+
+    public PrecompJoinOptimizerTest(final AbstractPcjIndexSetProvider provider) {
+        this.provider = provider;
+    }
+    @Test
+    public void testThreeIndex() throws Exception {
+
+        final String q7 = ""//
+                + "SELECT ?s ?t ?u " //
+                + "{" //
+                + "  ?s a ?t ."//
+                + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+                + "  ?u <uri:talksTo> ?s . "//
+                + "}";//
+
+        final String q8 = ""//
+                + "SELECT ?e ?l ?c " //
+                + "{" //
+                + "  ?e a ?l ."//
+                + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+                + "  ?c <uri:talksTo> ?e . "//
+                + "}";//
+
+        final String q9 = ""//
+                + "SELECT ?f ?m ?d " //
+                + "{" //
+                + "  ?f a ?m ."//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "}";//
+
+        final String q15 = ""//
+                + "SELECT ?f ?m ?d ?e ?l ?c " //
+                + "{" //
+                + "  ?f a ?m ."//
+                + "  ?e a ?l ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "  ?c <uri:talksTo> ?e . "//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+                + "}";//
+
+        final SPARQLParser parser = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser.parseQuery(q15, null);
+        final ParsedQuery pq2 = parser.parseQuery(q7, null);
+        final ParsedQuery pq3 = parser.parseQuery(q8, null);
+        final ParsedQuery pq4 = parser.parseQuery(q9, null);
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                (Projection) pq3.getTupleExpr());
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                (Projection) pq4.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+
+        list.add(extTup1);
+
+        final List<QueryModelNode> optTupNodes = Lists.newArrayList();
+        optTupNodes.add(extTup2);
+        optTupNodes.add(extTup3);
+
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, true, provider);
+        final TupleExpr te = pq1.getTupleExpr();
+        pcj.optimize(te, null, null);
+
+        final NodeCollector nc = new NodeCollector();
+        te.visit(nc);
+
+        Assert.assertEquals(nc.qNodes.size(), optTupNodes.size());
+        for (final QueryModelNode node : nc.qNodes) {
+            Assert.assertTrue(optTupNodes.contains(node));
+        }
+
+    }
+
+    @Test
+    public void testThreeIndex2() throws Exception {
+
+        final String q1 = ""//
+                + "SELECT ?f ?m ?d ?e ?l ?c " //
+                + "{" //
+                + "  ?f a ?m ."//
+                + "  ?c a ?l ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "  ?e <uri:talksTo> ?c . "//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?e ."//
+                + "  ?m <uri:talksTo> ?e . "//
+                + "}";//
+
+        final String q2 = ""//
+                + "SELECT ?u ?s ?t " //
+                + "{" //
+                + "  ?s a ?t ."//
+                + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+                + "  ?u <uri:talksTo> ?s . "//
+                + "}";//
+
+        final String q3 = ""//
+                + "SELECT ?e ?c ?l " //
+                + "{" //
+                + "  ?c a ?l ."//
+                + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?e ."//
+                + "  ?e <uri:talksTo> ?c . "//
+                + "}";//
+
+        final String q4 = ""//
+                + "SELECT ?d ?f ?m " //
+                + "{" //
+                + "  ?f a ?m ."//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "}";//
+
+        final SPARQLParser parser = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser.parseQuery(q1, null);
+        final ParsedQuery pq2 = parser.parseQuery(q2, null);
+        final ParsedQuery pq3 = parser.parseQuery(q3, null);
+        final ParsedQuery pq4 = parser.parseQuery(q4, null);
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                (Projection) pq3.getTupleExpr());
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                (Projection) pq4.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+
+        list.add(extTup1);
+
+        final List<StatementPattern> spList = StatementPatternCollector
+                .process(pq1.getTupleExpr());
+        final List<QueryModelNode> optTupNodes = Lists.newArrayList();
+        optTupNodes.add(extTup3);
+        optTupNodes.add(spList.get(6));
+        optTupNodes.add(extTup2);
+
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, true, provider);
+        final TupleExpr te = pq1.getTupleExpr();
+        pcj.optimize(te, null, null);
+
+        final NodeCollector nc = new NodeCollector();
+        te.visit(nc);
+
+        Assert.assertEquals(nc.qNodes, Sets.newHashSet(optTupNodes));
+
+    }
+
+    @Test
+    public void testSixIndex() throws Exception {
+
+        final String q1 = ""//
+                + "SELECT ?f ?m ?d ?h ?i " //
+                + "{" //
+                + "  ?f a ?m ."//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "  ?d <uri:hangOutWith> ?f ." //
+                + "  ?f <uri:hangOutWith> ?h ." //
+                + "  ?f <uri:associatesWith> ?i ." //
+                + "  ?i <uri:associatesWith> ?h ." //
+                + "}";//
+
+        final String q2 = ""//
+                + "SELECT ?t ?s ?u " //
+                + "{" //
+                + "  ?s a ?t ."//
+                + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+                + "  ?u <uri:talksTo> ?s . "//
+                + "}";//
+
+        final String q3 = ""//
+                + "SELECT ?s ?t ?u " //
+                + "{" //
+                + "  ?s <uri:hangOutWith> ?t ." //
+                + "  ?t <uri:hangOutWith> ?u ." //
+                + "}";//
+
+        final String q4 = ""//
+                + "SELECT ?s ?t ?u " //
+                + "{" //
+                + "  ?s <uri:associatesWith> ?t ." //
+                + "  ?t <uri:associatesWith> ?u ." //
+                + "}";//
+
+        final String q5 = ""//
+                + "SELECT ?m ?f ?d " //
+                + "{" //
+                + "  ?f a ?m ."//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "}";//
+
+        final String q6 = ""//
+                + "SELECT ?d ?f ?h " //
+                + "{" //
+                + "  ?d <uri:hangOutWith> ?f ." //
+                + "  ?f <uri:hangOutWith> ?h ." //
+                + "}";//
+
+        final String q7 = ""//
+                + "SELECT ?f ?i ?h " //
+                + "{" //
+                + "  ?f <uri:associatesWith> ?i ." //
+                + "  ?i <uri:associatesWith> ?h ." //
+                + "}";//
+
+        final SPARQLParser parser = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser.parseQuery(q1, null);
+        final ParsedQuery pq2 = parser.parseQuery(q2, null);
+        final ParsedQuery pq3 = parser.parseQuery(q3, null);
+        final ParsedQuery pq4 = parser.parseQuery(q4, null);
+        final ParsedQuery pq5 = parser.parseQuery(q5, null);
+        final ParsedQuery pq6 = parser.parseQuery(q6, null);
+        final ParsedQuery pq7 = parser.parseQuery(q7, null);
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                (Projection) pq3.getTupleExpr());
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                (Projection) pq4.getTupleExpr());
+        final SimpleExternalTupleSet extTup4 = new SimpleExternalTupleSet(
+                (Projection) pq5.getTupleExpr());
+        final SimpleExternalTupleSet extTup5 = new SimpleExternalTupleSet(
+                (Projection) pq6.getTupleExpr());
+        final SimpleExternalTupleSet extTup6 = new SimpleExternalTupleSet(
+                (Projection) pq7.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+
+        list.add(extTup2);
+        list.add(extTup1);
+        list.add(extTup3);
+
+        final List<QueryModelNode> optTupNodes = Lists.newArrayList();
+        optTupNodes.add(extTup4);
+        optTupNodes.add(extTup6);
+        optTupNodes.add(extTup5);
+
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, true, provider);
+        final TupleExpr te = pq1.getTupleExpr();
+        pcj.optimize(te, null, null);
+
+        System.out.println(te);
+
+        final NodeCollector nc = new NodeCollector();
+        te.visit(nc);
+
+        Assert.assertEquals(nc.qNodes, Sets.newHashSet(optTupNodes));
+
+    }
+
+    @Test
+    public void twoFourIndexWithFilterTest() throws Exception {
+
+        final String q1 = ""//
+                + "SELECT ?f ?m ?d ?e ?l ?c " //
+                + "{" //
+                + "  Filter(?f > \"5\")." //
+                + "  Filter(?e > \"5\")." //
+                + "  ?f a ?m ."//
+                + "  ?e a ?l ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "  ?c <uri:talksTo> ?e . "//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+                + "}";//
+
+        final String q2 = ""//
+                + "SELECT ?s ?t ?u " //
+                + "{" //
+                + "  ?s a ?t ."//
+                + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+                + "  ?u <uri:talksTo> ?s . "//
+                + "}";//
+
+        final String q3 = ""//
+                + "SELECT ?s ?t ?u " //
+                + "{" //
+                + " Filter(?s > \"5\") ."//
+                + "  ?s a ?t ."//
+                + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+                + "  ?u <uri:talksTo> ?s . "//
+                + "}";//
+
+        final String q4 = ""//
+                + "SELECT ?f ?m ?d " //
+                + "{" //
+                + " Filter(?f > \"5\") ."//
+                + "  ?f a ?m ."//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "}";//
+
+        final String q5 = ""//
+                + "SELECT ?e ?l ?c " //
+                + "{" //
+                + " Filter(?e > \"5\") ."//
+                + "  ?e a ?l ."//
+                + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+                + "  ?c <uri:talksTo> ?e . "//
+                + "}";//
+
+        final SPARQLParser parser = new SPARQLParser();
+
+        ParsedQuery pq1 = null;
+        ParsedQuery pq2 = null;
+        ParsedQuery pq3 = null;
+        ParsedQuery pq4 = null;
+        ParsedQuery pq5 = null;
+
+        try {
+            pq1 = parser.parseQuery(q1, null);
+            pq2 = parser.parseQuery(q2, null);
+            pq3 = parser.parseQuery(q3, null);
+            pq4 = parser.parseQuery(q4, null);
+            pq5 = parser.parseQuery(q5, null);
+
+        } catch (final Exception e) {
+            e.printStackTrace();
+        }
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                (Projection) pq3.getTupleExpr());
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                (Projection) pq4.getTupleExpr());
+        final SimpleExternalTupleSet extTup4 = new SimpleExternalTupleSet(
+                (Projection) pq5.getTupleExpr());
 
-	@Test
-	public void testThreeIndex() throws Exception {
-
-		final String q7 = ""//
-				+ "SELECT ?s ?t ?u " //
-				+ "{" //
-				+ "  ?s a ?t ."//
-				+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-				+ "  ?u <uri:talksTo> ?s . "//
-				+ "}";//
-
-		final String q8 = ""//
-				+ "SELECT ?e ?l ?c " //
-				+ "{" //
-				+ "  ?e a ?l ."//
-				+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-				+ "  ?c <uri:talksTo> ?e . "//
-				+ "}";//
-
-		final String q9 = ""//
-				+ "SELECT ?f ?m ?d " //
-				+ "{" //
-				+ "  ?f a ?m ."//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "}";//
-
-		final String q15 = ""//
-				+ "SELECT ?f ?m ?d ?e ?l ?c " //
-				+ "{" //
-				+ "  ?f a ?m ."//
-				+ "  ?e a ?l ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "  ?c <uri:talksTo> ?e . "//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-				+ "}";//
-
-		final SPARQLParser parser = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser.parseQuery(q15, null);
-		final ParsedQuery pq2 = parser.parseQuery(q7, null);
-		final ParsedQuery pq3 = parser.parseQuery(q8, null);
-		final ParsedQuery pq4 = parser.parseQuery(q9, null);
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				(Projection) pq3.getTupleExpr());
-		final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				(Projection) pq4.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-
-		list.add(extTup1);
-
-		final List<QueryModelNode> optTupNodes = Lists.newArrayList();
-		optTupNodes.add(extTup2);
-		optTupNodes.add(extTup3);
-
-		final PCJOptimizer pcj = new PCJOptimizer(list, true);
-		final TupleExpr te = pq1.getTupleExpr();
-		pcj.optimize(te, null, null);
-
-		final NodeCollector nc = new NodeCollector();
-		te.visit(nc);
-
-		Assert.assertEquals(nc.qNodes.size(), optTupNodes.size());
-		for (final QueryModelNode node : nc.qNodes) {
-			Assert.assertTrue(optTupNodes.contains(node));
-		}
-
-	}
-
-	@Test
-	public void testThreeIndex2() throws Exception {
-
-		final String q1 = ""//
-				+ "SELECT ?f ?m ?d ?e ?l ?c " //
-				+ "{" //
-				+ "  ?f a ?m ."//
-				+ "  ?c a ?l ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "  ?e <uri:talksTo> ?c . "//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?e ."//
-				+ "  ?m <uri:talksTo> ?e . "//
-				+ "}";//
-
-		final String q2 = ""//
-				+ "SELECT ?u ?s ?t " //
-				+ "{" //
-				+ "  ?s a ?t ."//
-				+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-				+ "  ?u <uri:talksTo> ?s . "//
-				+ "}";//
-
-		final String q3 = ""//
-				+ "SELECT ?e ?c ?l " //
-				+ "{" //
-				+ "  ?c a ?l ."//
-				+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?e ."//
-				+ "  ?e <uri:talksTo> ?c . "//
-				+ "}";//
-
-		final String q4 = ""//
-				+ "SELECT ?d ?f ?m " //
-				+ "{" //
-				+ "  ?f a ?m ."//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "}";//
-
-		final SPARQLParser parser = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser.parseQuery(q1, null);
-		final ParsedQuery pq2 = parser.parseQuery(q2, null);
-		final ParsedQuery pq3 = parser.parseQuery(q3, null);
-		final ParsedQuery pq4 = parser.parseQuery(q4, null);
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				(Projection) pq3.getTupleExpr());
-		final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				(Projection) pq4.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-
-		list.add(extTup1);
-
-		final List<StatementPattern> spList = StatementPatternCollector
-				.process(pq1.getTupleExpr());
-		final List<QueryModelNode> optTupNodes = Lists.newArrayList();
-		optTupNodes.add(extTup3);
-		optTupNodes.add(spList.get(6));
-		optTupNodes.add(extTup2);
-
-		final PCJOptimizer pcj = new PCJOptimizer(list, true);
-		final TupleExpr te = pq1.getTupleExpr();
-		pcj.optimize(te, null, null);
-
-		final NodeCollector nc = new NodeCollector();
-		te.visit(nc);
-
-		Assert.assertEquals(nc.qNodes, Sets.newHashSet(optTupNodes));
-
-	}
-
-	@Test
-	public void testSixIndex() throws Exception {
-
-		final String q1 = ""//
-				+ "SELECT ?f ?m ?d ?h ?i " //
-				+ "{" //
-				+ "  ?f a ?m ."//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "  ?d <uri:hangOutWith> ?f ." //
-				+ "  ?f <uri:hangOutWith> ?h ." //
-				+ "  ?f <uri:associatesWith> ?i ." //
-				+ "  ?i <uri:associatesWith> ?h ." //
-				+ "}";//
-
-		final String q2 = ""//
-				+ "SELECT ?t ?s ?u " //
-				+ "{" //
-				+ "  ?s a ?t ."//
-				+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-				+ "  ?u <uri:talksTo> ?s . "//
-				+ "}";//
-
-		final String q3 = ""//
-				+ "SELECT ?s ?t ?u " //
-				+ "{" //
-				+ "  ?s <uri:hangOutWith> ?t ." //
-				+ "  ?t <uri:hangOutWith> ?u ." //
-				+ "}";//
-
-		final String q4 = ""//
-				+ "SELECT ?s ?t ?u " //
-				+ "{" //
-				+ "  ?s <uri:associatesWith> ?t ." //
-				+ "  ?t <uri:associatesWith> ?u ." //
-				+ "}";//
-
-		final String q5 = ""//
-				+ "SELECT ?m ?f ?d " //
-				+ "{" //
-				+ "  ?f a ?m ."//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "}";//
-
-		final String q6 = ""//
-				+ "SELECT ?d ?f ?h " //
-				+ "{" //
-				+ "  ?d <uri:hangOutWith> ?f ." //
-				+ "  ?f <uri:hangOutWith> ?h ." //
-				+ "}";//
-
-		final String q7 = ""//
-				+ "SELECT ?f ?i ?h " //
-				+ "{" //
-				+ "  ?f <uri:associatesWith> ?i ." //
-				+ "  ?i <uri:associatesWith> ?h ." //
-				+ "}";//
-
-		final SPARQLParser parser = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser.parseQuery(q1, null);
-		final ParsedQuery pq2 = parser.parseQuery(q2, null);
-		final ParsedQuery pq3 = parser.parseQuery(q3, null);
-		final ParsedQuery pq4 = parser.parseQuery(q4, null);
-		final ParsedQuery pq5 = parser.parseQuery(q5, null);
-		final ParsedQuery pq6 = parser.parseQuery(q6, null);
-		final ParsedQuery pq7 = parser.parseQuery(q7, null);
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				(Projection) pq3.getTupleExpr());
-		final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				(Projection) pq4.getTupleExpr());
-		final SimpleExternalTupleSet extTup4 = new SimpleExternalTupleSet(
-				(Projection) pq5.getTupleExpr());
-		final SimpleExternalTupleSet extTup5 = new SimpleExternalTupleSet(
-				(Projection) pq6.getTupleExpr());
-		final SimpleExternalTupleSet extTup6 = new SimpleExternalTupleSet(
-				(Projection) pq7.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-
-		list.add(extTup2);
-		list.add(extTup1);
-		list.add(extTup3);
-
-		final List<QueryModelNode> optTupNodes = Lists.newArrayList();
-		optTupNodes.add(extTup4);
-		optTupNodes.add(extTup6);
-		optTupNodes.add(extTup5);
-
-		final PCJOptimizer pcj = new PCJOptimizer(list, true);
-		final TupleExpr te = pq1.getTupleExpr();
-		pcj.optimize(te, null, null);
-
-		System.out.println(te);
-
-		final NodeCollector nc = new NodeCollector();
-		te.visit(nc);
-
-		Assert.assertEquals(nc.qNodes, Sets.newHashSet(optTupNodes));
-
-	}
-
-	@Test
-	public void twoFourIndexWithFilterTest() throws Exception {
-
-		final String q1 = ""//
-				+ "SELECT ?f ?m ?d ?e ?l ?c " //
-				+ "{" //
-				+ "  Filter(?f > \"5\")." //
-				+ "  Filter(?e > \"5\")." //
-				+ "  ?f a ?m ."//
-				+ "  ?e a ?l ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "  ?c <uri:talksTo> ?e . "//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-				+ "}";//
-
-		final String q2 = ""//
-				+ "SELECT ?s ?t ?u " //
-				+ "{" //
-				+ "  ?s a ?t ."//
-				+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-				+ "  ?u <uri:talksTo> ?s . "//
-				+ "}";//
-
-		final String q3 = ""//
-				+ "SELECT ?s ?t ?u " //
-				+ "{" //
-				+ " Filter(?s > \"5\") ."//
-				+ "  ?s a ?t ."//
-				+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-				+ "  ?u <uri:talksTo> ?s . "//
-				+ "}";//
-
-		final String q4 = ""//
-				+ "SELECT ?f ?m ?d " //
-				+ "{" //
-				+ " Filter(?f > \"5\") ."//
-				+ "  ?f a ?m ."//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "}";//
-
-		final String q5 = ""//
-				+ "SELECT ?e ?l ?c " //
-				+ "{" //
-				+ " Filter(?e > \"5\") ."//
-				+ "  ?e a ?l ."//
-				+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-				+ "  ?c <uri:talksTo> ?e . "//
-				+ "}";//
-
-		final SPARQLParser parser = new SPARQLParser();
-
-		ParsedQuery pq1 = null;
-		ParsedQuery pq2 = null;
-		ParsedQuery pq3 = null;
-		ParsedQuery pq4 = null;
-		ParsedQuery pq5 = null;
-
-		try {
-			pq1 = parser.parseQuery(q1, null);
-			pq2 = parser.parseQuery(q2, null);
-			pq3 = parser.parseQuery(q3, null);
-			pq4 = parser.parseQuery(q4, null);
-			pq5 = parser.parseQuery(q5, null);
-
-		} catch (final Exception e) {
-			e.printStackTrace();
-		}
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				(Projection) pq3.getTupleExpr());
-		final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				(Projection) pq4.getTupleExpr());
-		final SimpleExternalTupleSet extTup4 = new SimpleExternalTupleSet(
-				(Projection) pq5.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-
-		list.add(extTup2);
-		list.add(extTup1);
-
-		final List<ExternalTupleSet> list2 = new ArrayList<ExternalTupleSet>();
-
-		list2.add(extTup3);
-		list2.add(extTup4);
-
-		final PCJOptimizer pcj = new PCJOptimizer(list, true);
-		final TupleExpr te = pq1.getTupleExpr();
-		pcj.optimize(te, null, null);
-
-		System.out.println(te);
-
-		final NodeCollector nc = new NodeCollector();
-		te.visit(nc);
-
-		Assert.assertEquals(nc.qNodes.size(), list2.size());
-
-		for (final QueryModelNode e : nc.qNodes) {
-			Assert.assertTrue(list2.contains(e));
-		}
-
-	}
-
-	public static class NodeCollector extends
-			QueryModelVisitorBase<RuntimeException> {
-
-		Set<QueryModelNode> qNodes = new HashSet<>();
-
-		@Override
-		public void meetNode(final QueryModelNode node) {
-			if (node instanceof StatementPattern
-					|| node instanceof ExternalTupleSet) {
-				qNodes.add(node);
-			}
-			super.meetNode(node);
-
-		}
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+
+        list.add(extTup2);
+        list.add(extTup1);
+
+        final List<ExternalTupleSet> list2 = new ArrayList<ExternalTupleSet>();
+
+        list2.add(extTup3);
+        list2.add(extTup4);
+
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, true, provider);
+        final TupleExpr te = pq1.getTupleExpr();
+        pcj.optimize(te, null, null);
+
+        System.out.println(te);
+
+        final NodeCollector nc = new NodeCollector();
+        te.visit(nc);
+
+        Assert.assertEquals(nc.qNodes.size(), list2.size());
+
+        for (final QueryModelNode e : nc.qNodes) {
+            Assert.assertTrue(list2.contains(e));
+        }
+
+    }
+
+    public static class NodeCollector extends
+    QueryModelVisitorBase<RuntimeException> {
+
+        Set<QueryModelNode> qNodes = new HashSet<>();
+
+        @Override
+        public void meetNode(final QueryModelNode node) {
+            if (node instanceof StatementPattern
+                    || node instanceof ExternalTupleSet) {
+                qNodes.add(node);
+            }
+            super.meetNode(node);
+
+        }
 
         public List<QueryModelNode> getNodes() {
             return Lists.newArrayList(qNodes);
         }
 
-	}
+    }
 
 }



[3/8] incubator-rya git commit: RYA-303 Mongo PCJ Support. Closes #172.

Posted by ca...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/mongo/MongoPCJIndexIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/mongo/MongoPCJIndexIT.java b/extras/indexing/src/test/java/org/apache/rya/indexing/mongo/MongoPCJIndexIT.java
new file mode 100644
index 0000000..1503b53
--- /dev/null
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/mongo/MongoPCJIndexIT.java
@@ -0,0 +1,233 @@
+/**
+ * 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.
+ */
+package org.apache.rya.indexing.mongo;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
+import org.apache.rya.api.RdfCloudTripleStoreConstants;
+import org.apache.rya.api.client.Install.InstallConfiguration;
+import org.apache.rya.api.client.RyaClient;
+import org.apache.rya.api.client.mongo.MongoConnectionDetails;
+import org.apache.rya.api.client.mongo.MongoRyaClientFactory;
+import org.apache.rya.indexing.accumulo.ConfigUtils;
+import org.apache.rya.mongodb.MongoDBRdfConfiguration;
+import org.apache.rya.mongodb.MongoITBase;
+import org.apache.rya.sail.config.RyaSailFactory;
+import org.junit.Test;
+import org.openrdf.model.Statement;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.model.impl.ValueFactoryImpl;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.QueryLanguage;
+import org.openrdf.query.TupleQuery;
+import org.openrdf.query.TupleQueryResult;
+import org.openrdf.query.impl.MapBindingSet;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.repository.sail.SailRepositoryConnection;
+import org.openrdf.sail.Sail;
+
+public class MongoPCJIndexIT extends MongoITBase {
+    private static final ValueFactory VF = ValueFactoryImpl.getInstance();
+
+    @Override
+    protected void updateConfiguration(final MongoDBRdfConfiguration conf) {
+        conf.setBoolean(ConfigUtils.USE_MONGO, true);
+        conf.setBoolean(ConfigUtils.USE_PCJ, false);
+    }
+
+    @Test
+    public void sparqlQuery_Test() throws Exception {
+        // Setup a Rya Client.
+        final MongoConnectionDetails connectionDetails = getConnectionDetails();
+        final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, getMongoClient());
+        final String pcjQuery = "SELECT ?name WHERE {"
+        		+ " ?name <urn:likes> <urn:icecream> ."
+        		+ " ?name <urn:hasEyeColor> <urn:blue> ."
+        		+ " }";
+
+        // Install an instance of Rya and load statements.
+        ryaClient.getInstall().install(conf.getRyaInstanceName(), InstallConfiguration.builder()
+                .setEnablePcjIndex(true)
+                .build());
+        ryaClient.getLoadStatements().loadStatements(conf.getRyaInstanceName(), getStatements());
+        final String pcjId = ryaClient.getCreatePCJ().createPCJ(conf.getRyaInstanceName(), pcjQuery);
+        ryaClient.getBatchUpdatePCJ().batchUpdate(conf.getRyaInstanceName(), pcjId);
+
+        //purge contents of rya triples collection
+        getMongoClient().getDatabase(conf.getRyaInstanceName()).getCollection(conf.getTriplesCollectionName()).drop();
+        
+        //run the query.  since the triples collection is gone, if the results match, they came from the PCJ index.
+        conf.setBoolean(ConfigUtils.USE_PCJ, true);
+        conf.setBoolean(ConfigUtils.USE_OPTIMAL_PCJ, true);
+        conf.setBoolean(ConfigUtils.DISPLAY_QUERY_PLAN, true);
+        final Sail sail = RyaSailFactory.getInstance(conf);
+        SailRepositoryConnection conn = new SailRepository(sail).getConnection();
+        conn.begin();
+        final TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, pcjQuery);
+        tupleQuery.setBinding(RdfCloudTripleStoreConfiguration.CONF_QUERYPLAN_FLAG, RdfCloudTripleStoreConstants.VALUE_FACTORY.createLiteral(true));
+        final TupleQueryResult rez = tupleQuery.evaluate();
+        final Set<BindingSet> results = new HashSet<>();
+        while(rez.hasNext()) {
+            final BindingSet bs = rez.next();
+            results.add(bs);
+        }
+        
+     // Verify the correct results were loaded into the PCJ table.
+        final Set<BindingSet> expectedResults = new HashSet<>();
+
+        MapBindingSet bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:Alice"));
+        expectedResults.add(bs);
+
+        bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:Bob"));
+        expectedResults.add(bs);
+
+        bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:Charlie"));
+        expectedResults.add(bs);
+
+        bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:David"));
+        expectedResults.add(bs);
+
+        bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:Eve"));
+        expectedResults.add(bs);
+
+        bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:Frank"));
+        expectedResults.add(bs);
+
+        assertEquals(6, results.size());
+        assertEquals(expectedResults, results);
+    }
+    
+    @Test
+    public void sparqlQuery_Test_complex() throws Exception {
+        // Setup a Rya Client.
+        final MongoConnectionDetails connectionDetails = getConnectionDetails();
+        final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, getMongoClient());
+        final String pcjQuery = "SELECT ?name WHERE {"
+        		+ " ?name <urn:likes> <urn:icecream> ."
+        		+ " ?name <urn:hasEyeColor> <urn:blue> ."
+        		+ " }";
+        
+        final String testQuery = 
+        		  "SELECT ?name WHERE {"
+        		+ " ?name <urn:hasHairColor> <urn:brown> ."
+        		+ " ?name <urn:likes> <urn:icecream> ."
+        		+ " ?name <urn:hasEyeColor> <urn:blue> ."
+        		+ " }";
+
+        // Install an instance of Rya and load statements.
+        conf.setBoolean(ConfigUtils.USE_PCJ, true);
+        conf.setBoolean(ConfigUtils.USE_OPTIMAL_PCJ, true);
+        conf.setBoolean(ConfigUtils.DISPLAY_QUERY_PLAN, true);
+        ryaClient.getInstall().install(conf.getRyaInstanceName(), InstallConfiguration.builder()
+                .setEnablePcjIndex(true)
+                .build());
+        ryaClient.getLoadStatements().loadStatements(conf.getRyaInstanceName(), getStatements());
+        final String pcjId = ryaClient.getCreatePCJ().createPCJ(conf.getRyaInstanceName(), pcjQuery);
+        ryaClient.getBatchUpdatePCJ().batchUpdate(conf.getRyaInstanceName(), pcjId);
+
+        System.out.println("Triples: " + getMongoClient().getDatabase(conf.getRyaInstanceName()).getCollection(conf.getTriplesCollectionName()).count());
+        System.out.println("PCJS: " + getMongoClient().getDatabase(conf.getRyaInstanceName()).getCollection("pcjs").count());
+        
+        //run the query.  since the triples collection is gone, if the results match, they came from the PCJ index.
+        final Sail sail = RyaSailFactory.getInstance(conf);
+        SailRepositoryConnection conn = new SailRepository(sail).getConnection();
+        conn.begin();
+        final TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, testQuery);
+        tupleQuery.setBinding(RdfCloudTripleStoreConfiguration.CONF_QUERYPLAN_FLAG, RdfCloudTripleStoreConstants.VALUE_FACTORY.createLiteral(true));
+        final TupleQueryResult rez = tupleQuery.evaluate();
+
+        final Set<BindingSet> results = new HashSet<>();
+        while(rez.hasNext()) {
+            final BindingSet bs = rez.next();
+            results.add(bs);
+        }
+        
+     // Verify the correct results were loaded into the PCJ table.
+        final Set<BindingSet> expectedResults = new HashSet<>();
+
+        MapBindingSet bs = new MapBindingSet();
+        bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:David"));
+        expectedResults.add(bs);
+
+        bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:Eve"));
+        expectedResults.add(bs);
+
+        bs = new MapBindingSet();
+        bs.addBinding("name", VF.createURI("urn:Frank"));
+        expectedResults.add(bs);
+
+        assertEquals(3, results.size());
+        assertEquals(expectedResults, results);
+    }
+    
+    private MongoConnectionDetails getConnectionDetails() {
+        final java.util.Optional<char[]> password = conf.getMongoPassword() != null ?
+                java.util.Optional.of(conf.getMongoPassword().toCharArray()) :
+                    java.util.Optional.empty();
+
+        return new MongoConnectionDetails(
+                conf.getMongoHostname(),
+                Integer.parseInt(conf.getMongoPort()),
+                java.util.Optional.ofNullable(conf.getMongoUser()),
+                password);
+    }
+
+    private Set<Statement> getStatements() throws Exception {
+    	final Set<Statement> statements = new HashSet<>();
+    	statements.add(VF.createStatement(VF.createURI("urn:Alice"), VF.createURI("urn:likes"), VF.createURI("urn:icecream")));
+        statements.add(VF.createStatement(VF.createURI("urn:Bob"), VF.createURI("urn:likes"), VF.createURI("urn:icecream")));
+        statements.add(VF.createStatement(VF.createURI("urn:Charlie"), VF.createURI("urn:likes"), VF.createURI("urn:icecream")));
+        statements.add(VF.createStatement(VF.createURI("urn:David"), VF.createURI("urn:likes"), VF.createURI("urn:icecream")));
+        statements.add(VF.createStatement(VF.createURI("urn:Eve"), VF.createURI("urn:likes"), VF.createURI("urn:icecream")));
+        statements.add(VF.createStatement(VF.createURI("urn:Frank"), VF.createURI("urn:likes"), VF.createURI("urn:icecream")));
+        statements.add(VF.createStatement(VF.createURI("urn:George"), VF.createURI("urn:likes"), VF.createURI("urn:icecream")));
+        statements.add(VF.createStatement(VF.createURI("urn:Hillary"), VF.createURI("urn:likes"), VF.createURI("urn:icecream")));
+        
+        statements.add(VF.createStatement(VF.createURI("urn:Alice"), VF.createURI("urn:hasEyeColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:Bob"), VF.createURI("urn:hasEyeColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:Charlie"), VF.createURI("urn:hasEyeColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:David"), VF.createURI("urn:hasEyeColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:Eve"), VF.createURI("urn:hasEyeColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:Frank"), VF.createURI("urn:hasEyeColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:George"), VF.createURI("urn:hasEyeColor"), VF.createURI("urn:green")));
+        statements.add(VF.createStatement(VF.createURI("urn:Hillary"), VF.createURI("urn:hasEyeColor"), VF.createURI("urn:brown")));
+        
+        statements.add(VF.createStatement(VF.createURI("urn:Alice"), VF.createURI("urn:hasHairColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:Bob"), VF.createURI("urn:hasHairColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:Charlie"), VF.createURI("urn:hasHairColor"), VF.createURI("urn:blue")));
+        statements.add(VF.createStatement(VF.createURI("urn:David"), VF.createURI("urn:hasHairColor"), VF.createURI("urn:brown")));
+        statements.add(VF.createStatement(VF.createURI("urn:Eve"), VF.createURI("urn:hasHairColor"), VF.createURI("urn:brown")));
+        statements.add(VF.createStatement(VF.createURI("urn:Frank"), VF.createURI("urn:hasHairColor"), VF.createURI("urn:brown")));
+        statements.add(VF.createStatement(VF.createURI("urn:George"), VF.createURI("urn:hasHairColor"), VF.createURI("urn:blonde")));
+        statements.add(VF.createStatement(VF.createURI("urn:Hillary"), VF.createURI("urn:hasHairColor"), VF.createURI("urn:blonde")));
+        return statements;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/mongo/MongoPcjIntegrationTest.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/mongo/MongoPcjIntegrationTest.java b/extras/indexing/src/test/java/org/apache/rya/indexing/mongo/MongoPcjIntegrationTest.java
new file mode 100644
index 0000000..af81cf6
--- /dev/null
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/mongo/MongoPcjIntegrationTest.java
@@ -0,0 +1,374 @@
+/**
+ * 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.
+ */
+package org.apache.rya.indexing.mongo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.rya.indexing.IndexPlanValidator.IndexPlanValidator;
+import org.apache.rya.indexing.accumulo.ConfigUtils;
+import org.apache.rya.indexing.external.PcjIntegrationTestingUtil;
+import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig;
+import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType;
+import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinUpdaterType;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.mongodb.pcj.MongoPcjIndexSetProvider;
+import org.apache.rya.indexing.mongodb.pcj.MongoPcjQueryNode;
+import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
+import org.apache.rya.mongodb.MongoDBRdfConfiguration;
+import org.apache.rya.mongodb.MongoITBase;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
+import org.apache.rya.sail.config.RyaSailFactory;
+import org.junit.Test;
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.LiteralImpl;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.model.vocabulary.RDF;
+import org.openrdf.model.vocabulary.RDFS;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.QueryLanguage;
+import org.openrdf.query.QueryResultHandlerException;
+import org.openrdf.query.TupleQueryResultHandler;
+import org.openrdf.query.TupleQueryResultHandlerException;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.parser.ParsedQuery;
+import org.openrdf.query.parser.sparql.SPARQLParser;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.repository.sail.SailRepositoryConnection;
+import org.openrdf.sail.Sail;
+
+import com.google.common.collect.Lists;
+
+public class MongoPcjIntegrationTest extends MongoITBase {
+    private static final URI talksTo = new URIImpl("uri:talksTo");
+    private static final URI sub = new URIImpl("uri:entity");
+    private static final URI sub2 = new URIImpl("uri:entity2");
+    private static final URI subclass = new URIImpl("uri:class");
+    private static final URI subclass2 = new URIImpl("uri:class2");
+    private static final URI obj = new URIImpl("uri:obj");
+    private static final URI obj2 = new URIImpl("uri:obj2");
+
+    private void addPCJS(final SailRepositoryConnection conn) throws Exception {
+        conn.add(sub, RDF.TYPE, subclass);
+        conn.add(sub, RDFS.LABEL, new LiteralImpl("label"));
+        conn.add(sub, talksTo, obj);
+
+        conn.add(sub2, RDF.TYPE, subclass2);
+        conn.add(sub2, RDFS.LABEL, new LiteralImpl("label2"));
+        conn.add(sub2, talksTo, obj2);
+    }
+
+    @Override
+    protected void updateConfiguration(final MongoDBRdfConfiguration conf) {
+        conf.set(PrecomputedJoinIndexerConfig.PCJ_STORAGE_TYPE, PrecomputedJoinStorageType.MONGO.name());
+        conf.set(PrecomputedJoinIndexerConfig.PCJ_UPDATER_TYPE, PrecomputedJoinUpdaterType.NO_UPDATE.name());
+    }
+
+    @Test
+    public void testEvaluateSingleIndex() throws Exception {
+        final Sail nonPcjSail = RyaSailFactory.getInstance(conf);
+        final MongoDBRdfConfiguration pcjConf = conf.clone();
+        pcjConf.setBoolean(ConfigUtils.USE_PCJ, true);
+        final Sail pcjSail = RyaSailFactory.getInstance(pcjConf);
+        final SailRepositoryConnection conn = new SailRepository(nonPcjSail).getConnection();
+        final SailRepositoryConnection pcjConn = new SailRepository(pcjSail).getConnection();
+        addPCJS(pcjConn);
+        try {
+            final String indexSparqlString = ""//
+                    + "SELECT ?e ?l ?c " //
+                    + "{" //
+                    + "  ?e a ?c . "//
+                    + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                    + "}";//
+
+            PcjIntegrationTestingUtil.createAndPopulatePcj(conn, getMongoClient(), conf.getMongoDBName() + 1, conf.getRyaInstanceName(), indexSparqlString);
+
+            final String queryString = ""//
+                    + "SELECT ?e ?c ?l ?o " //
+                    + "{" //
+                    + "  ?e a ?c . "//
+                    + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                    + "  ?e <uri:talksTo> ?o . "//
+                    + "}";//
+
+            final CountingResultHandler crh1 = new CountingResultHandler();
+            final CountingResultHandler crh2 = new CountingResultHandler();
+
+            conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString).evaluate(crh1);
+            pcjConn.prepareTupleQuery(QueryLanguage.SPARQL, queryString).evaluate(crh2);
+
+            assertEquals(crh1.getCount(), crh2.getCount());
+        } finally {
+            conn.close();
+            pcjConn.close();
+            nonPcjSail.shutDown();
+            pcjSail.shutDown();
+        }
+    }
+
+    @Test
+    public void testEvaluateOneIndex() throws Exception {
+        final Sail nonPcjSail = RyaSailFactory.getInstance(conf);
+        final MongoDBRdfConfiguration pcjConf = conf.clone();
+        pcjConf.setBoolean(ConfigUtils.USE_PCJ, true);
+        final Sail pcjSail = RyaSailFactory.getInstance(pcjConf);
+        final SailRepositoryConnection conn = new SailRepository(nonPcjSail).getConnection();
+        final SailRepositoryConnection pcjConn = new SailRepository(pcjSail).getConnection();
+        addPCJS(pcjConn);
+        try {
+            final URI superclass = new URIImpl("uri:superclass");
+            final URI superclass2 = new URIImpl("uri:superclass2");
+
+            conn.add(subclass, RDF.TYPE, superclass);
+            conn.add(subclass2, RDF.TYPE, superclass2);
+            conn.add(obj, RDFS.LABEL, new LiteralImpl("label"));
+            conn.add(obj2, RDFS.LABEL, new LiteralImpl("label2"));
+
+            final String indexSparqlString = ""//
+                    + "SELECT ?dog ?pig ?duck  " //
+                    + "{" //
+                    + "  ?pig a ?dog . "//
+                    + "  ?pig <http://www.w3.org/2000/01/rdf-schema#label> ?duck "//
+                    + "}";//
+
+            final CountingResultHandler crh1 = new CountingResultHandler();
+            final CountingResultHandler crh2 = new CountingResultHandler();
+
+            PcjIntegrationTestingUtil.createAndPopulatePcj(conn, getMongoClient(), conf.getMongoDBName() + 1, conf.getRyaInstanceName(), indexSparqlString);
+
+            conn.prepareTupleQuery(QueryLanguage.SPARQL, indexSparqlString).evaluate(crh1);
+            PcjIntegrationTestingUtil.deleteCoreRyaTables(getMongoClient(), conf.getRyaInstanceName(), conf.getTriplesCollectionName());
+            pcjConn.prepareTupleQuery(QueryLanguage.SPARQL, indexSparqlString).evaluate(crh2);
+
+            assertEquals(crh1.count, crh2.count);
+        } finally {
+            conn.close();
+            pcjConn.close();
+            nonPcjSail.shutDown();
+            pcjSail.shutDown();
+        }
+    }
+
+    @Test
+    public void testEvaluateTwoIndexValidate() throws Exception {
+        final Sail nonPcjSail = RyaSailFactory.getInstance(conf);
+        final MongoDBRdfConfiguration pcjConf = conf.clone();
+        pcjConf.setBoolean(ConfigUtils.USE_PCJ, true);
+        final Sail pcjSail = RyaSailFactory.getInstance(pcjConf);
+        final SailRepositoryConnection conn = new SailRepository(nonPcjSail).getConnection();
+        final SailRepositoryConnection pcjConn = new SailRepository(pcjSail).getConnection();
+        addPCJS(pcjConn);
+        try {
+            final URI superclass = new URIImpl("uri:superclass");
+            final URI superclass2 = new URIImpl("uri:superclass2");
+
+            conn.add(subclass, RDF.TYPE, superclass);
+            conn.add(subclass2, RDF.TYPE, superclass2);
+            conn.add(obj, RDFS.LABEL, new LiteralImpl("label"));
+            conn.add(obj2, RDFS.LABEL, new LiteralImpl("label2"));
+
+            final String indexSparqlString = ""//
+                    + "SELECT ?dog ?pig ?duck  " //
+                    + "{" //
+                    + "  ?pig a ?dog . "//
+                    + "  ?pig <http://www.w3.org/2000/01/rdf-schema#label> ?duck "//
+                    + "}";//
+
+            final String indexSparqlString2 = ""//
+                    + "SELECT ?o ?f ?e ?c ?l  " //
+                    + "{" //
+                    + "  ?e <uri:talksTo> ?o . "//
+                    + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l. "//
+                    + "  ?c a ?f . " //
+                    + "}";//
+
+            final String queryString = ""//
+                    + "SELECT ?e ?c ?l ?f ?o " //
+                    + "{" //
+                    + "  ?e a ?c . "//
+                    + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l. "//
+                    + "  ?e <uri:talksTo> ?o . "//
+                    + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l. "//
+                    + "  ?c a ?f . " //
+                    + "}";//
+
+            PcjIntegrationTestingUtil.createAndPopulatePcj(conn, getMongoClient(), conf.getMongoDBName() + 1, conf.getRyaInstanceName(), indexSparqlString);
+            final MongoPcjQueryNode ais1 = new MongoPcjQueryNode(conf, conf.getMongoDBName() + 1);
+
+            PcjIntegrationTestingUtil.createAndPopulatePcj(conn, getMongoClient(), conf.getMongoDBName() + 2, conf.getRyaInstanceName(), indexSparqlString2);
+            final MongoPcjQueryNode ais2 = new MongoPcjQueryNode(conf, conf.getMongoDBName() + 2);
+
+            final List<ExternalTupleSet> index = new ArrayList<>();
+            index.add(ais1);
+            index.add(ais2);
+
+            ParsedQuery pq = null;
+            final SPARQLParser sp = new SPARQLParser();
+            pq = sp.parseQuery(queryString, null);
+            final List<TupleExpr> teList = Lists.newArrayList();
+            final TupleExpr te = pq.getTupleExpr();
+
+            final PCJOptimizer pcj = new PCJOptimizer(index, false, new MongoPcjIndexSetProvider(new StatefulMongoDBRdfConfiguration(conf, getMongoClient())));
+            pcj.optimize(te, null, null);
+            teList.add(te);
+
+            final IndexPlanValidator ipv = new IndexPlanValidator(false);
+
+            assertTrue(ipv.isValid(te));
+        } finally {
+            conn.close();
+            pcjConn.close();
+            nonPcjSail.shutDown();
+            pcjSail.shutDown();
+        }
+    }
+
+    @Test
+    public void testEvaluateThreeIndexValidate() throws Exception {
+        final Sail nonPcjSail = RyaSailFactory.getInstance(conf);
+        final MongoDBRdfConfiguration pcjConf = conf.clone();
+        pcjConf.setBoolean(ConfigUtils.USE_PCJ, true);
+        final Sail pcjSail = RyaSailFactory.getInstance(pcjConf);
+        final SailRepositoryConnection conn = new SailRepository(nonPcjSail).getConnection();
+        final SailRepositoryConnection pcjConn = new SailRepository(pcjSail).getConnection();
+        addPCJS(pcjConn);
+        try {
+            final URI superclass = new URIImpl("uri:superclass");
+            final URI superclass2 = new URIImpl("uri:superclass2");
+
+            final URI howlsAt = new URIImpl("uri:howlsAt");
+            final URI subType = new URIImpl("uri:subType");
+            final URI superSuperclass = new URIImpl("uri:super_superclass");
+
+            conn.add(subclass, RDF.TYPE, superclass);
+            conn.add(subclass2, RDF.TYPE, superclass2);
+            conn.add(obj, RDFS.LABEL, new LiteralImpl("label"));
+            conn.add(obj2, RDFS.LABEL, new LiteralImpl("label2"));
+            conn.add(sub, howlsAt, superclass);
+            conn.add(superclass, subType, superSuperclass);
+
+            final String indexSparqlString = ""//
+                    + "SELECT ?dog ?pig ?duck  " //
+                    + "{" //
+                    + "  ?pig a ?dog . "//
+                    + "  ?pig <http://www.w3.org/2000/01/rdf-schema#label> ?duck "//
+                    + "}";//
+
+            final String indexSparqlString2 = ""//
+                    + "SELECT ?o ?f ?e ?c ?l  " //
+                    + "{" //
+                    + "  ?e <uri:talksTo> ?o . "//
+                    + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l. "//
+                    + "  ?c a ?f . " //
+                    + "}";//
+
+            final String indexSparqlString3 = ""//
+                    + "SELECT ?wolf ?sheep ?chicken  " //
+                    + "{" //
+                    + "  ?wolf <uri:howlsAt> ?sheep . "//
+                    + "  ?sheep <uri:subType> ?chicken. "//
+                    + "}";//
+
+            final String queryString = ""//
+                    + "SELECT ?e ?c ?l ?f ?o " //
+                    + "{" //
+                    + "  ?e a ?c . "//
+                    + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l. "//
+                    + "  ?e <uri:talksTo> ?o . "//
+                    + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l. "//
+                    + "  ?c a ?f . " //
+                    + "  ?e <uri:howlsAt> ?f. "//
+                    + "  ?f <uri:subType> ?o. "//
+                    + "}";//
+
+            PcjIntegrationTestingUtil.createAndPopulatePcj(conn, getMongoClient(), conf.getMongoDBName() + 1, conf.getRyaInstanceName(), indexSparqlString);
+            final MongoPcjQueryNode ais1 = new MongoPcjQueryNode(conf, conf.getMongoDBName() + 1);
+
+            PcjIntegrationTestingUtil.createAndPopulatePcj(conn, getMongoClient(), conf.getMongoDBName() + 2, conf.getRyaInstanceName(), indexSparqlString2);
+            final MongoPcjQueryNode ais2 = new MongoPcjQueryNode(conf, conf.getMongoDBName() + 2);
+
+            PcjIntegrationTestingUtil.createAndPopulatePcj(conn, getMongoClient(), conf.getMongoDBName() + 3, conf.getRyaInstanceName(), indexSparqlString3);
+            final MongoPcjQueryNode ais3 = new MongoPcjQueryNode(conf, conf.getMongoDBName() + 3);
+
+            final List<ExternalTupleSet> index = new ArrayList<>();
+            index.add(ais1);
+            index.add(ais3);
+            index.add(ais2);
+
+            ParsedQuery pq = null;
+            final SPARQLParser sp = new SPARQLParser();
+            pq = sp.parseQuery(queryString, null);
+            final List<TupleExpr> teList = Lists.newArrayList();
+            final TupleExpr te = pq.getTupleExpr();
+
+            final PCJOptimizer pcj = new PCJOptimizer(index, false, new MongoPcjIndexSetProvider(new StatefulMongoDBRdfConfiguration(conf, getMongoClient())));
+            pcj.optimize(te, null, null);
+
+            teList.add(te);
+
+            final IndexPlanValidator ipv = new IndexPlanValidator(false);
+
+            assertTrue(ipv.isValid(te));
+        } finally {
+            conn.close();
+            pcjConn.close();
+            nonPcjSail.shutDown();
+            pcjSail.shutDown();
+        }
+    }
+
+    public static class CountingResultHandler implements TupleQueryResultHandler {
+        private int count = 0;
+
+        public int getCount() {
+            return count;
+        }
+
+        public void resetCount() {
+            count = 0;
+        }
+
+        @Override
+        public void startQueryResult(final List<String> arg0) throws TupleQueryResultHandlerException {
+        }
+
+        @Override
+        public void handleSolution(final BindingSet arg0) throws TupleQueryResultHandlerException {
+            count++;
+            System.out.println(arg0);
+        }
+
+        @Override
+        public void endQueryResult() throws TupleQueryResultHandlerException {
+        }
+
+        @Override
+        public void handleBoolean(final boolean arg0) throws QueryResultHandlerException {
+
+        }
+
+        @Override
+        public void handleLinks(final List<String> arg0) throws QueryResultHandlerException {
+
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerTest.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerTest.java b/extras/indexing/src/test/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerTest.java
index 31f4e7b..d28d826 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerTest.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerTest.java
@@ -19,17 +19,24 @@ package org.apache.rya.indexing.pcj.matching;
  * under the License.
  */
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.rya.indexing.IndexPlanValidator.IndexedExecutionPlanGenerator;
 import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
-
+import org.apache.rya.indexing.mongodb.pcj.MongoPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.matching.provider.AbstractPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
+import org.apache.rya.mongodb.EmbeddedMongoSingleton;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
 import org.junit.Assert;
 import org.junit.Test;
-import org.openrdf.query.MalformedQueryException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 import org.openrdf.query.algebra.Projection;
 import org.openrdf.query.algebra.QueryModelNode;
 import org.openrdf.query.algebra.StatementPattern;
@@ -38,14 +45,30 @@ import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
 import org.openrdf.query.parser.ParsedQuery;
 import org.openrdf.query.parser.sparql.SPARQLParser;
 
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
+@RunWith(Parameterized.class)
 public class PCJOptimizerTest {
+    private final AbstractPcjIndexSetProvider provider;
+
+    @Parameterized.Parameters
+    public static Collection providers() throws Exception {
+        final StatefulMongoDBRdfConfiguration conf = new StatefulMongoDBRdfConfiguration(new Configuration(), EmbeddedMongoSingleton.getNewMongoClient());
+        return Lists.<AbstractPcjIndexSetProvider> newArrayList(
+                new AccumuloIndexSetProvider(new Configuration()),
+                new MongoPcjIndexSetProvider(conf)
+                );
+    }
+
+    public PCJOptimizerTest(final AbstractPcjIndexSetProvider provider) {
+        this.provider = provider;
+    }
 
     @Test
     public void testBasicSegment() throws Exception {
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?e ?c ?l" //
                 + "{" //
                 + "  ?e a ?c . "//
@@ -53,29 +76,30 @@ public class PCJOptimizerTest {
                 + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?a ?b ?m" //
                 + "{" //
                 + "  ?a a ?b . "//
                 + "  OPTIONAL {?a <uri:talksTo> ?m}  . "//
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
 
-        TupleExpr unOpt = te1.clone();
-        List<QueryModelNode> remainingNodes = getNodes(te1);
-        Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+        final TupleExpr unOpt = te1.clone();
+        final List<QueryModelNode> remainingNodes = getNodes(te1);
+        final Set<QueryModelNode> unMatchedNodes = new HashSet<>();
         unMatchedNodes.add(remainingNodes.get(2));
 
-        SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj);
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
 
         Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
@@ -86,7 +110,7 @@ public class PCJOptimizerTest {
     @Test
     public void testSegmentWithUnion() throws Exception {
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?e ?c ?l" //
                 + "{" //
                 + " {?e <uri:p1> <uri:o1>. } UNION { ?e a ?c. OPTIONAL {?e <uri:talksTo> ?l}. ?e <uri:p5> <uri:o4>. ?e <uri:p4> <uri:o3> }  . "//
@@ -94,7 +118,7 @@ public class PCJOptimizerTest {
                 + "  ?e <uri:p3> <uri:o2>  . "//
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?a ?b ?m" //
                 + "{" //
                 + " ?a <uri:p5> <uri:o4> ." //
@@ -103,33 +127,34 @@ public class PCJOptimizerTest {
                 + "  ?a a ?b . "//
                 + "}";//
 
-        String query3 = ""//
+        final String query3 = ""//
                 + "SELECT ?h ?i" //
                 + "{" //
                 + "  ?h <uri:p2> ?i . "//
                 + "  ?h <uri:p3> <uri:o2>  . "//
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        ParsedQuery pq3 = parser.parseQuery(query3, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
-        TupleExpr te3 = pq3.getTupleExpr();
-
-        TupleExpr unOpt = te1.clone();
-        List<QueryModelNode> remainingNodes = getNodes(te1);
-        Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final ParsedQuery pq3 = parser.parseQuery(query3, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
+        final TupleExpr te3 = pq3.getTupleExpr();
+
+        final TupleExpr unOpt = te1.clone();
+        final List<QueryModelNode> remainingNodes = getNodes(te1);
+        final Set<QueryModelNode> unMatchedNodes = new HashSet<>();
         unMatchedNodes.add(remainingNodes.get(0));
 
-        SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
-        SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
+        final SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj1);
         externalList.add(pcj2);
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
 
         Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
@@ -142,7 +167,7 @@ public class PCJOptimizerTest {
     public void testExactMatchLargeReOrdered() throws Exception {
 
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
                 + "{" //
                 + "  ?a <uri:p0> ?b ." //
@@ -155,7 +180,7 @@ public class PCJOptimizerTest {
                 + "  OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
                 + "{" //
                 + "  ?a <uri:p0> ?b ." //
@@ -168,20 +193,21 @@ public class PCJOptimizerTest {
                 + "  OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
 
-        TupleExpr unOpt = te1.clone();
+        final TupleExpr unOpt = te1.clone();
 
-        SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj);
 
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
 
         Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, new HashSet<QueryModelNode>()));
@@ -190,7 +216,7 @@ public class PCJOptimizerTest {
     @Test
     public void testSubsetMatchLargeReOrdered() throws Exception {
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
                 + "{" //
                 + "  ?a <uri:p0> ?b ." //
@@ -203,7 +229,7 @@ public class PCJOptimizerTest {
                 + "  OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
                 + "{" //
                 + "  ?a <uri:p0> ?b ." //
@@ -213,15 +239,15 @@ public class PCJOptimizerTest {
                 + "  OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
 
-        TupleExpr unOpt = te1.clone();
-        List<QueryModelNode> remainingNodes = getNodes(te1);
-        Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+        final TupleExpr unOpt = te1.clone();
+        final List<QueryModelNode> remainingNodes = getNodes(te1);
+        final Set<QueryModelNode> unMatchedNodes = new HashSet<>();
         unMatchedNodes.add(remainingNodes.get(8));
         unMatchedNodes.add(remainingNodes.get(9));
         unMatchedNodes.add(remainingNodes.get(10));
@@ -229,11 +255,12 @@ public class PCJOptimizerTest {
         unMatchedNodes.add(remainingNodes.get(12));
         unMatchedNodes.add(remainingNodes.get(7));
 
-        SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj);
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
 
         Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
@@ -242,7 +269,7 @@ public class PCJOptimizerTest {
     @Test
     public void testSwitchTwoBoundVars() throws Exception {
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?a ?b ?c " //
                 + "{" //
                 + "  ?a <uri:p0> ?c ." //
@@ -254,7 +281,7 @@ public class PCJOptimizerTest {
                 + " ?b <uri:p3> <uri:o3> " //
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?a ?b ?c " //
                 + "{" //
                 + " ?a <uri:p2> <uri:o2>. " //
@@ -264,23 +291,24 @@ public class PCJOptimizerTest {
                 + "  ?b<uri:p1> ?c " //
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
 
-        TupleExpr unOpt = te1.clone();
-        List<QueryModelNode> remainingNodes = getNodes(te1);
-        Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+        final TupleExpr unOpt = te1.clone();
+        final List<QueryModelNode> remainingNodes = getNodes(te1);
+        final Set<QueryModelNode> unMatchedNodes = new HashSet<>();
         unMatchedNodes.add(remainingNodes.get(1));
         unMatchedNodes.add(remainingNodes.get(2));
 
-        SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj);
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
 
         Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
@@ -289,7 +317,7 @@ public class PCJOptimizerTest {
     @Test
     public void testSegmentWithLargeUnion() throws Exception {
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?e ?c ?l" //
                 + "{" //
                 + " {?e <uri:p1> <uri:o1>. } UNION { " //
@@ -304,7 +332,7 @@ public class PCJOptimizerTest {
                 + "  ?e <uri:p3> <uri:o2>  . "//
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?a ?b ?c " //
                 + "{" //
                 + " ?a <uri:p2> <uri:o2>. " //
@@ -314,35 +342,36 @@ public class PCJOptimizerTest {
                 + "  ?b<uri:p1> ?c " //
                 + "}";//
 
-        String query3 = ""//
+        final String query3 = ""//
                 + "SELECT ?h ?i" //
                 + "{" //
                 + "  ?h <uri:p2> ?i . "//
                 + "  ?h <uri:p3> <uri:o2>  . "//
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        ParsedQuery pq3 = parser.parseQuery(query3, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
-        TupleExpr te3 = pq3.getTupleExpr();
-
-        TupleExpr unOpt = te1.clone();
-        List<QueryModelNode> remainingNodes = getNodes(te1);
-        Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final ParsedQuery pq3 = parser.parseQuery(query3, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
+        final TupleExpr te3 = pq3.getTupleExpr();
+
+        final TupleExpr unOpt = te1.clone();
+        final List<QueryModelNode> remainingNodes = getNodes(te1);
+        final Set<QueryModelNode> unMatchedNodes = new HashSet<>();
         unMatchedNodes.add(remainingNodes.get(0));
         unMatchedNodes.add(remainingNodes.get(2));
         unMatchedNodes.add(remainingNodes.get(3));
 
-        SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
-        SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
+        final SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj1);
         externalList.add(pcj2);
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
 
         Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
@@ -352,7 +381,7 @@ public class PCJOptimizerTest {
     @Test
     public void testSegmentWithUnionAndFilters() throws Exception {
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?e ?c ?l" //
                 + "{" //
                 + " Filter(?e = <uri:s1>) " //
@@ -362,7 +391,7 @@ public class PCJOptimizerTest {
                 + "  ?e <uri:p3> <uri:o2>  . "//
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?a ?b ?m" //
                 + "{" //
                 + " Filter(?b = <uri:s2>) " //
@@ -372,7 +401,7 @@ public class PCJOptimizerTest {
                 + "  ?a a ?b . "//
                 + "}";//
 
-        String query3 = ""//
+        final String query3 = ""//
                 + "SELECT ?h ?i" //
                 + "{" //
                 + " Filter(?h = <uri:s1>) " //
@@ -380,26 +409,27 @@ public class PCJOptimizerTest {
                 + "  ?h <uri:p3> <uri:o2>  . "//
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        ParsedQuery pq3 = parser.parseQuery(query3, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
-        TupleExpr te3 = pq3.getTupleExpr();
-
-        TupleExpr unOpt = te1.clone();
-        List<QueryModelNode> remainingNodes = getNodes(te1);
-        Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final ParsedQuery pq3 = parser.parseQuery(query3, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
+        final TupleExpr te3 = pq3.getTupleExpr();
+
+        final TupleExpr unOpt = te1.clone();
+        final List<QueryModelNode> remainingNodes = getNodes(te1);
+        final Set<QueryModelNode> unMatchedNodes = new HashSet<>();
         unMatchedNodes.add(remainingNodes.get(0));
 
-        SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
-        SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
+        final SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj1);
         externalList.add(pcj2);
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
 
         Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
@@ -409,7 +439,7 @@ public class PCJOptimizerTest {
     @Test
     public void testSegmentWithLeftJoinsAndFilters() throws Exception {
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?e ?c ?l" //
                 + "{" //
                 + " Filter(?e = <uri:s1>) " //
@@ -419,14 +449,14 @@ public class PCJOptimizerTest {
                 + " OPTIONAL {?e <uri:p2> ?c } . "//
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?e ?c ?l" //
                 + "{" //
                 + " Filter(?c = <uri:s2>) " //
                 + " ?e <uri:p1> <uri:o1>. " + " OPTIONAL {?e <uri:p2> ?l}. " + " ?c <uri:p3> <uri:o3>  . "//
                 + "}";//
 
-        String query3 = ""//
+        final String query3 = ""//
                 + "SELECT ?e ?c" //
                 + "{" //
                 + " Filter(?e = <uri:s1>) " //
@@ -434,23 +464,24 @@ public class PCJOptimizerTest {
                 + " OPTIONAL {?e <uri:p2> ?c } . "//
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        ParsedQuery pq3 = parser.parseQuery(query3, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
-        TupleExpr te3 = pq3.getTupleExpr();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final ParsedQuery pq3 = parser.parseQuery(query3, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
+        final TupleExpr te3 = pq3.getTupleExpr();
 
-        TupleExpr unOpt = te1.clone();
+        final TupleExpr unOpt = te1.clone();
 
-        SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
-        SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
+        final SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj1);
         externalList.add(pcj2);
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
 
         Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, new HashSet<QueryModelNode>()));
@@ -459,7 +490,7 @@ public class PCJOptimizerTest {
     @Test
     public void testJoinMatcherRejectsLeftJoinPcj() throws Exception {
 
-        String query1 = ""//
+        final String query1 = ""//
                 + "SELECT ?e ?c ?l" //
                 + "{" //
                 + "  ?e a ?c . "//
@@ -467,7 +498,7 @@ public class PCJOptimizerTest {
                 + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
                 + "}";//
 
-        String query2 = ""//
+        final String query2 = ""//
                 + "SELECT ?a ?b ?m" //
                 + "{" //
                 + "  ?a a ?b . "//
@@ -475,43 +506,44 @@ public class PCJOptimizerTest {
                 + "  OPTIONAL {?a <http://www.w3.org/2000/01/rdf-schema#label> ?m}  . "//
                 + "}";//
 
-        SPARQLParser parser = new SPARQLParser();
-        ParsedQuery pq1 = parser.parseQuery(query1, null);
-        ParsedQuery pq2 = parser.parseQuery(query2, null);
-        TupleExpr te1 = pq1.getTupleExpr();
-        TupleExpr te2 = pq2.getTupleExpr();
-        TupleExpr expected = te1.clone();
+        final SPARQLParser parser = new SPARQLParser();
+        final ParsedQuery pq1 = parser.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser.parseQuery(query2, null);
+        final TupleExpr te1 = pq1.getTupleExpr();
+        final TupleExpr te2 = pq2.getTupleExpr();
+        final TupleExpr expected = te1.clone();
 
-        SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
-        List<ExternalTupleSet> externalList = new ArrayList<>();
+        final SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+        final List<ExternalTupleSet> externalList = new ArrayList<>();
         externalList.add(pcj);
 
-        PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+        provider.setIndices(externalList);
+        final PCJOptimizer optimizer = new PCJOptimizer(externalList, false, provider);
         optimizer.optimize(te1, null, null);
         Assert.assertEquals(expected, te1);
 
     }
 
 
-    private List<QueryModelNode> getNodes(TupleExpr te) {
-        NodeCollector collector = new NodeCollector();
+    private List<QueryModelNode> getNodes(final TupleExpr te) {
+        final NodeCollector collector = new NodeCollector();
         te.visit(collector);
         return collector.getNodes();
     }
 
-    private boolean validatePcj(TupleExpr optTupleExp, TupleExpr unOptTup, List<ExternalTupleSet> pcjs, Set<QueryModelNode> expUnmatchedNodes) {
+    private boolean validatePcj(final TupleExpr optTupleExp, final TupleExpr unOptTup, final List<ExternalTupleSet> pcjs, final Set<QueryModelNode> expUnmatchedNodes) {
 
-        IndexedExecutionPlanGenerator iep = new IndexedExecutionPlanGenerator(
+        final IndexedExecutionPlanGenerator iep = new IndexedExecutionPlanGenerator(
                 unOptTup, pcjs);
-        List<ExternalTupleSet> indexList = iep.getNormalizedIndices();
-        Set<QueryModelNode> indexSet = new HashSet<>();
-        for(ExternalTupleSet etup: indexList) {
+        final List<ExternalTupleSet> indexList = iep.getNormalizedIndices();
+        final Set<QueryModelNode> indexSet = new HashSet<>();
+        for(final ExternalTupleSet etup: indexList) {
             indexSet.add(etup);
         }
 
-        Set<QueryModelNode> tupNodes = Sets.newHashSet(getNodes(optTupleExp));
+        final Set<QueryModelNode> tupNodes = Sets.newHashSet(getNodes(optTupleExp));
 
-        Set<QueryModelNode> diff =  Sets.difference(tupNodes, indexSet);
+        final Set<QueryModelNode> diff =  Sets.difference(tupNodes, indexSet);
         return diff.equals(expUnmatchedNodes);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/periodic/KafkaLatencyBenchmark.java
----------------------------------------------------------------------
diff --git a/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/periodic/KafkaLatencyBenchmark.java b/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/periodic/KafkaLatencyBenchmark.java
index e19e965..e75d499 100644
--- a/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/periodic/KafkaLatencyBenchmark.java
+++ b/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/periodic/KafkaLatencyBenchmark.java
@@ -113,8 +113,8 @@ public class KafkaLatencyBenchmark implements AutoCloseable {
     public KafkaLatencyBenchmark(final CommonOptions options, final BenchmarkOptions benchmarkOptions) throws AccumuloException, AccumuloSecurityException {
         this.options = Objects.requireNonNull(options);
         this.benchmarkOptions = Objects.requireNonNull(benchmarkOptions);
-        this.client = Objects.requireNonNull(options.buildRyaClient());
-        this.startTime = LocalDateTime.now();
+        client = Objects.requireNonNull(options.buildRyaClient());
+        startTime = LocalDateTime.now();
 
         logger.info("Running {} with the following input parameters:\n{}\n{}", this.getClass(), options, benchmarkOptions);
     }
@@ -172,7 +172,7 @@ public class KafkaLatencyBenchmark implements AutoCloseable {
                 + "group by ?type";
 
         logger.info("Query: {}", sparql);
-        return client.getCreatePCJ().get().createPCJ(options.getRyaInstance(), sparql, ImmutableSet.of(ExportStrategy.KAFKA));
+        return client.getCreatePCJ().createPCJ(options.getRyaInstance(), sparql, ImmutableSet.of(ExportStrategy.KAFKA));
     }
 
     private String issuePeriodicQuery(final PeriodicQueryCommand periodicOptions) throws InstanceDoesNotExistException, RyaClientException {
@@ -352,7 +352,7 @@ public class KafkaLatencyBenchmark implements AutoCloseable {
                 logger.info("Publishing {} Observations", observationsPerIteration);
                 final long t1 = System.currentTimeMillis();
                 loadStatements.loadStatements(ryaInstanceName, statements);
-                logger.info("Published {} observations in in {}s", observationsPerIteration, ((System.currentTimeMillis() - t1)/1000.0));
+                logger.info("Published {} observations in in {}s", observationsPerIteration, (System.currentTimeMillis() - t1)/1000.0);
                 logger.info("Updating published totals...");
                 for(int typeId = 0; typeId < numTypes; typeId++) {
                     typeToStatMap.get(typePrefix + typeId).total.addAndGet(observationsPerTypePerIteration);
@@ -367,7 +367,7 @@ public class KafkaLatencyBenchmark implements AutoCloseable {
         }
 
         public void setShutdownOperation(final Runnable f) {
-            this.shutdownOperation = f;
+            shutdownOperation = f;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/query/PCJOptimizerBenchmark.java
----------------------------------------------------------------------
diff --git a/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/query/PCJOptimizerBenchmark.java b/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/query/PCJOptimizerBenchmark.java
index 6841048..cf4ca8f 100644
--- a/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/query/PCJOptimizerBenchmark.java
+++ b/extras/rya.benchmark/src/main/java/org/apache/rya/benchmark/query/PCJOptimizerBenchmark.java
@@ -28,9 +28,11 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Queue;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
 import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
 import org.openjdk.jmh.annotations.Benchmark;
 import org.openjdk.jmh.annotations.Param;
 import org.openjdk.jmh.annotations.Scope;
@@ -106,12 +108,12 @@ public class PCJOptimizerBenchmark {
                     final BenchmarkValues chainedValues = new BenchmarkValues(
                             makeChainedQuery(benchmarkParams),
                             makeChainedPCJOptimizer(benchmarkParams));
-                    this.chainedBenchmarkValues.put(benchmarkParams, chainedValues);
+                    chainedBenchmarkValues.put(benchmarkParams, chainedValues);
 
                     final BenchmarkValues unchainedValues = new BenchmarkValues(
                             makeUnchainedQuery(benchmarkParams),
                             makeUnchainedPCJOptimizer(benchmarkParams));
-                    this.unchainedBenchmarkValues.put(benchmarkParams, unchainedValues);
+                    unchainedBenchmarkValues.put(benchmarkParams, unchainedValues);
                 }
             }
         }
@@ -215,7 +217,7 @@ public class PCJOptimizerBenchmark {
         }
 
         // Create the optimizer.
-        return new PCJOptimizer(indices, false);
+        return new PCJOptimizer(indices, false, new AccumuloIndexSetProvider(new Configuration()));
     }
 
     private static PCJOptimizer makeChainedPCJOptimizer(final BenchmarkParams params) throws Exception {
@@ -252,7 +254,7 @@ public class PCJOptimizerBenchmark {
         }
 
         // Create the optimizer.
-        return new PCJOptimizer(indices, false);
+        return new PCJOptimizer(indices, false, new AccumuloIndexSetProvider(new Configuration()));
     }
 
     private static String buildUnchainedSPARQL(final List<String> vars) {
@@ -274,8 +276,8 @@ public class PCJOptimizerBenchmark {
         }
 
         return "select " + Joiner.on(" ").join(vars) + " where { " +
-                    Joiner.on(" . ").join(statementPatterns) +
-                " . }" ;
+        Joiner.on(" . ").join(statementPatterns) +
+        " . }" ;
     }
 
     private static String buildChainedSPARQL(final List<String> vars) {
@@ -298,8 +300,8 @@ public class PCJOptimizerBenchmark {
 
         // Build the SPARQL query from the pieces.
         return "select " + Joiner.on(" ").join(vars) + " where { " +
-                    Joiner.on(" . ").join(statementPatterns) +
-                " . }" ;
+        Joiner.on(" . ").join(statementPatterns) +
+        " . }" ;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.benchmark/src/test/java/org/apache/rya/benchmark/query/QueryBenchmarkRunIT.java
----------------------------------------------------------------------
diff --git a/extras/rya.benchmark/src/test/java/org/apache/rya/benchmark/query/QueryBenchmarkRunIT.java b/extras/rya.benchmark/src/test/java/org/apache/rya/benchmark/query/QueryBenchmarkRunIT.java
index cc5ba8b..dd5fe68 100644
--- a/extras/rya.benchmark/src/test/java/org/apache/rya/benchmark/query/QueryBenchmarkRunIT.java
+++ b/extras/rya.benchmark/src/test/java/org/apache/rya/benchmark/query/QueryBenchmarkRunIT.java
@@ -148,7 +148,7 @@ public class QueryBenchmarkRunIT {
             final String pcjId = pcjs.createPcj(SPARQL_QUERY);
 
             // Batch update the PCJ using the Rya Client.
-            ryaClient.getBatchUpdatePCJ().get().batchUpdate(RYA_INSTANCE_NAME, pcjId);
+            ryaClient.getBatchUpdatePCJ().batchUpdate(RYA_INSTANCE_NAME, pcjId);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.indexing.pcj/pom.xml
----------------------------------------------------------------------
diff --git a/extras/rya.indexing.pcj/pom.xml b/extras/rya.indexing.pcj/pom.xml
index 797c2fb..1d4a4b6 100644
--- a/extras/rya.indexing.pcj/pom.xml
+++ b/extras/rya.indexing.pcj/pom.xml
@@ -48,6 +48,10 @@ under the License.
             <groupId>org.apache.rya</groupId>
             <artifactId>accumulo.rya</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.rya</groupId>
+            <artifactId>mongodb.rya</artifactId>
+        </dependency>
         
         <!-- Accumulo support dependencies. -->
         <dependency>
@@ -90,5 +94,11 @@ under the License.
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.rya</groupId>
+            <artifactId>mongodb.rya</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoBindingSetConverter.java
----------------------------------------------------------------------
diff --git a/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoBindingSetConverter.java b/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoBindingSetConverter.java
new file mode 100644
index 0000000..010f8bc
--- /dev/null
+++ b/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoBindingSetConverter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.rya.indexing.pcj.storage.mongo;
+
+import org.apache.rya.indexing.pcj.storage.accumulo.BindingSetConverter;
+import org.bson.Document;
+import org.openrdf.query.BindingSet;
+
+import edu.umd.cs.findbugs.annotations.DefaultAnnotation;
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * Converts {@link BindingSet}s into other representations. This library is
+ * intended to convert between BindingSet and {@link Document}.
+ */
+@DefaultAnnotation(NonNull.class)
+public interface MongoBindingSetConverter extends BindingSetConverter<Document> {
+
+    /**
+     * Converts a {@link BindingSet} into a MongoDB model.
+     *
+     * @param bindingSet - The BindingSet that will be converted. (not null)
+     * @return The BindingSet formatted as Mongo Bson object.
+     * @throws BindingSetConversionException The BindingSet was unable to be
+     *   converted. This will happen if one of the values could not be
+     *   converted into the target model.
+     */
+    public Document convert(BindingSet bindingSet) throws BindingSetConversionException;
+
+    /**
+     * Converts a MongoDB model into a {@link BindingSet}.
+     *
+     * @param bindingSet - The bson that will be converted. (not null)
+     * @return The BindingSet created from a Mongo Bson object.
+     * @throws BindingSetConversionException The Bson was unable to be
+     *   converted. This will happen if one of the values could not be
+     *   converted into a BindingSet.
+     */
+    public BindingSet convert(Document bindingSet) throws BindingSetConversionException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjDocuments.java
----------------------------------------------------------------------
diff --git a/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjDocuments.java b/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjDocuments.java
new file mode 100644
index 0000000..ecfbc1c
--- /dev/null
+++ b/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjDocuments.java
@@ -0,0 +1,445 @@
+/*
+ * 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.
+ */
+package org.apache.rya.indexing.pcj.storage.mongo;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.rya.api.domain.RyaType;
+import org.apache.rya.api.model.VisibilityBindingSet;
+import org.apache.rya.api.resolver.RdfToRyaConversions;
+import org.apache.rya.api.resolver.RyaToRdfConversions;
+import org.apache.rya.api.utils.CloseableIterator;
+import org.apache.rya.indexing.pcj.storage.PcjMetadata;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException;
+import org.apache.rya.indexing.pcj.storage.accumulo.PcjVarOrderFactory;
+import org.apache.rya.indexing.pcj.storage.accumulo.ShiftVarOrderFactory;
+import org.apache.rya.indexing.pcj.storage.accumulo.VariableOrder;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.MalformedQueryException;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.query.QueryLanguage;
+import org.openrdf.query.TupleQuery;
+import org.openrdf.query.TupleQueryResult;
+import org.openrdf.query.impl.MapBindingSet;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+
+import com.mongodb.MongoClient;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.util.JSON;
+
+/**
+ * Creates and modifies PCJs in MongoDB. PCJ's are stored as follows:
+ *
+ * <pre>
+ * <code>
+ * ----- PCJ Metadata Doc -----
+ * {
+ *   _id: [pcj_ID]_METADATA,
+ *   sparql: [sparql query to match results],
+ *   varOrders: [varOrder1, VarOrder2, ..., VarOrdern]
+ *   cardinality: [number of results]
+ * }
+ *
+ * ----- PCJ Results Doc -----
+ * {
+ *   pcjId: [pcj_ID],
+ *   visibilities: [visibilities]
+ *   [binding_var1]: {
+ *     uri: [type_uri],
+ *     value: [value]
+ *   }
+ *   .
+ *   .
+ *   .
+ *   [binding_varn]: {
+ *     uri: [type_uri],
+ *     value: [value]
+ *   }
+ * }
+ * </code>
+ * </pre>
+ */
+public class MongoPcjDocuments {
+    public static final String PCJ_COLLECTION_NAME = "pcjs";
+
+    // metadata fields
+    public static final String CARDINALITY_FIELD = "cardinality";
+    public static final String SPARQL_FIELD = "sparql";
+    public static final String PCJ_METADATA_ID = "_id";
+    public static final String VAR_ORDER_FIELD = "varOrders";
+
+    // pcj results fields
+    private static final String BINDING_VALUE = "value";
+    private static final String BINDING_TYPE = "rdfType";
+    private static final String VISIBILITIES_FIELD = "visibilities";
+    private static final String PCJ_ID = "pcjId";
+
+    private final MongoCollection<Document> pcjCollection;
+    private static final PcjVarOrderFactory pcjVarOrderFactory = new ShiftVarOrderFactory();
+
+    /**
+     * Creates a new {@link MongoPcjDocuments}.
+     * @param client - The {@link MongoClient} to use to connect to mongo.
+     * @param ryaInstanceName - The rya instance to connect to.
+     */
+    public MongoPcjDocuments(final MongoClient client, final String ryaInstanceName) {
+        requireNonNull(client);
+        requireNonNull(ryaInstanceName);
+        pcjCollection = client.getDatabase(ryaInstanceName).getCollection(PCJ_COLLECTION_NAME);
+    }
+
+    private String makeMetadataID(final String pcjId) {
+        return pcjId + "_METADATA";
+    }
+
+    /**
+     * Creates a {@link Document} containing the metadata defining the PCj.
+     *
+     * @param pcjId - Uniquely identifies a PCJ within Rya. (not null)
+     * @param sparql - The sparql query the PCJ will use.
+     * @return The document built around the provided metadata.
+     * @throws PCJStorageException - Thrown when the sparql query is malformed.
+     */
+    public Document makeMetadataDocument(final String pcjId, final String sparql) throws PCJStorageException {
+        requireNonNull(pcjId);
+        requireNonNull(sparql);
+
+        final Set<VariableOrder> varOrders;
+        try {
+            varOrders = pcjVarOrderFactory.makeVarOrders(sparql);
+        } catch (final MalformedQueryException e) {
+            throw new PCJStorageException("Can not create the PCJ. The SPARQL is malformed.", e);
+        }
+
+        return new Document()
+                .append(PCJ_METADATA_ID, makeMetadataID(pcjId))
+                .append(SPARQL_FIELD, sparql)
+                .append(CARDINALITY_FIELD, 0)
+                .append(VAR_ORDER_FIELD, varOrders);
+
+    }
+
+    /**
+     * Creates a new PCJ based on the provided metadata. The initial pcj results
+     * will be empty.
+     *
+     * @param pcjId - Uniquely identifies a PCJ within Rya.
+     * @param sparql - The query the pcj is assigned to.
+     * @throws PCJStorageException - Thrown when the sparql query is malformed.
+     */
+    public void createPcj(final String pcjId, final String sparql) throws PCJStorageException {
+        pcjCollection.insertOne(makeMetadataDocument(pcjId, sparql));
+    }
+
+    /**
+     * Creates a new PCJ document and populates it by scanning an instance of
+     * Rya for historic matches.
+     * <p>
+     * If any portion of this operation fails along the way, the partially
+     * create PCJ documents will be left in Mongo.
+     *
+     * @param ryaConn - Connects to the Rya that will be scanned. (not null)
+     * @param pcjId - Uniquely identifies a PCJ within Rya. (not null)
+     * @param sparql - The SPARQL query whose results will be loaded into the PCJ results document. (not null)
+     * @throws PCJStorageException The PCJ documents could not be create or the
+     *     values from Rya were not able to be loaded into it.
+     */
+    public void createAndPopulatePcj(
+            final RepositoryConnection ryaConn,
+            final String pcjId,
+            final String sparql) throws PCJStorageException {
+        checkNotNull(ryaConn);
+        checkNotNull(pcjId);
+        checkNotNull(sparql);
+
+        // Create the PCJ document in Mongo.
+        createPcj(pcjId, sparql);
+
+        // Load historic matches from Rya into the PCJ results document.
+        populatePcj(pcjId, ryaConn);
+    }
+
+    /**
+     * Gets the {@link PcjMetadata} from a provided PCJ Id.
+     *
+     * @param pcjId - The Id of the PCJ to get from MongoDB. (not null)
+     * @return - The {@link PcjMetadata} of the Pcj specified.
+     * @throws PCJStorageException The PCJ metadata document does not exist.
+     */
+    public PcjMetadata getPcjMetadata(final String pcjId) throws PCJStorageException {
+        requireNonNull(pcjId);
+
+        // since query by ID, there will only be one.
+        final Document result = pcjCollection.find(new Document(PCJ_METADATA_ID, makeMetadataID(pcjId))).first();
+
+        if(result == null) {
+            throw new PCJStorageException("The PCJ: " + pcjId + " does not exist.");
+        }
+
+        final String sparql = result.getString(SPARQL_FIELD);
+        final int cardinality = result.getInteger(CARDINALITY_FIELD, 0);
+        final List<List<String>> varOrders= (List<List<String>>) result.get(VAR_ORDER_FIELD);
+        final Set<VariableOrder> varOrder = new HashSet<>();
+        for(final List<String> vars : varOrders) {
+            varOrder.add(new VariableOrder(vars));
+        }
+
+        return new PcjMetadata(sparql, cardinality, varOrder);
+    }
+
+    /**
+     * Adds binding set results to a specific PCJ.
+     *
+     * @param pcjId - Uniquely identifies a PCJ within Rya. (not null)
+     * @param results - The binding set results. (not null)
+     */
+    public void addResults(final String pcjId, final Collection<VisibilityBindingSet> results) {
+        checkNotNull(pcjId);
+        checkNotNull(results);
+
+        final List<Document> pcjDocs = new ArrayList<>();
+        for (final VisibilityBindingSet vbs : results) {
+            // each binding gets it's own doc.
+            final Document bindingDoc = new Document(PCJ_ID, pcjId);
+            vbs.forEach(binding -> {
+                final RyaType type = RdfToRyaConversions.convertValue(binding.getValue());
+                bindingDoc.append(binding.getName(),
+                        new Document()
+                        .append(BINDING_TYPE, type.getDataType().stringValue())
+                        .append(BINDING_VALUE, type.getData())
+                        );
+            });
+            bindingDoc.append(VISIBILITIES_FIELD, vbs.getVisibility());
+            pcjDocs.add(bindingDoc);
+        }
+        pcjCollection.insertMany(pcjDocs);
+
+        // update cardinality in the metadata doc.
+        final int appendCardinality = pcjDocs.size();
+        final Bson query = new Document(PCJ_METADATA_ID, makeMetadataID(pcjId));
+        final Bson update = new Document("$inc", new Document(CARDINALITY_FIELD, appendCardinality));
+        pcjCollection.updateOne(query, update);
+    }
+
+    /**
+     * Purges all results from the PCJ results document with the provided Id.
+     *
+     * @param pcjId - The Id of the PCJ to purge. (not null)
+     */
+    public void purgePcjs(final String pcjId) {
+        requireNonNull(pcjId);
+
+        // remove every doc for the pcj, except the metadata
+        final Bson filter = new Document(PCJ_ID, pcjId);
+        pcjCollection.deleteMany(filter);
+
+        // reset cardinality
+        final Bson query = new Document(PCJ_METADATA_ID, makeMetadataID(pcjId));
+        final Bson update = new Document("$set", new Document(CARDINALITY_FIELD, 0));
+        pcjCollection.updateOne(query, update);
+    }
+
+    /**
+     * Scan Rya for results that solve the PCJ's query and store them in the PCJ
+     * document.
+     * <p>
+     * This method assumes the PCJ document has already been created.
+     *
+     * @param pcjId - The Id of the PCJ that will receive the results. (not null)
+     * @param ryaConn - A connection to the Rya store that will be queried to find results. (not null)
+     * @throws PCJStorageException If results could not be written to the PCJ results document,
+     *  the PCJ results document does not exist, or the query that is being execute was malformed.
+     */
+    public void populatePcj(final String pcjId, final RepositoryConnection ryaConn) throws PCJStorageException {
+        checkNotNull(pcjId);
+        checkNotNull(ryaConn);
+
+        try {
+            // Fetch the query that needs to be executed from the PCJ metadata document.
+            final PcjMetadata pcjMetadata = getPcjMetadata(pcjId);
+            final String sparql = pcjMetadata.getSparql();
+
+            // Query Rya for results to the SPARQL query.
+            final TupleQuery query = ryaConn.prepareTupleQuery(QueryLanguage.SPARQL, sparql);
+            final TupleQueryResult results = query.evaluate();
+
+            // Load batches of 1000 of them at a time into the PCJ results document.
+            final Set<VisibilityBindingSet> batch = new HashSet<>(1000);
+            while(results.hasNext()) {
+                final VisibilityBindingSet bs = new VisibilityBindingSet(results.next());
+                batch.add( bs );
+                if(batch.size() == 1000) {
+                    addResults(pcjId, batch);
+                    batch.clear();
+                }
+            }
+
+            if(!batch.isEmpty()) {
+                addResults(pcjId, batch);
+            }
+
+        } catch (RepositoryException | MalformedQueryException | QueryEvaluationException e) {
+            throw new PCJStorageException(
+                    "Could not populate a PCJ document with Rya results for the pcj with Id: " + pcjId, e);
+        }
+    }
+
+    /**
+     * List the document Ids of the PCJs that are stored in MongoDB
+     * for this instance of Rya.
+     *
+     * @return A list of pcj document Ids that hold PCJ index data for the current
+     *   instance of Rya.
+     */
+    public List<String> listPcjDocuments() {
+        final List<String> pcjIds = new ArrayList<>();
+
+        //This Bson string reads as:
+        //{} - no search criteria: find all
+        //{ _id: 1 } - only return the _id, which is the PCJ Id.
+        final FindIterable<Document> rez = pcjCollection.find((Bson) JSON.parse("{ }, { " + PCJ_METADATA_ID + ": 1 , _id: 0}"));
+        final Iterator<Document> iter = rez.iterator();
+        while(iter.hasNext()) {
+            pcjIds.add(iter.next().get(PCJ_METADATA_ID).toString().replace("_METADATA", ""));
+        }
+
+        return pcjIds;
+    }
+
+    /**
+     * Returns all of the results of a PCJ.
+     *
+     * @param pcjId
+     *            - The PCJ to get the results for. (not null)
+     * @return The authorized PCJ results.
+     */
+    public CloseableIterator<BindingSet> listResults(final String pcjId) {
+        requireNonNull(pcjId);
+
+        // get all results based on pcjId
+        return queryForBindings(new Document(PCJ_ID, pcjId));
+    }
+
+    /**
+     * Retrieves the stored {@link BindingSet} results for the provided pcjId.
+     *
+     * @param pcjId - The Id of the PCJ to retrieve results from.
+     * @param restrictionBindings - The collection of {@link BindingSet}s to restrict results.
+     * <p>
+     * Note: the result restrictions from {@link BindingSet}s are an OR
+     * over ANDS in that: <code>
+     *  [
+     *     bindingset: binding AND binding AND binding,
+     *     OR
+     *     bindingset: binding AND binding AND binding,
+     *     .
+     *     .
+     *     .
+     *     OR
+     *     bindingset: binding
+     *  ]
+     * </code>
+     * @return
+     */
+    public CloseableIterator<BindingSet> getResults(final String pcjId, final Collection<BindingSet> restrictionBindings) {
+        // empty bindings return all results.
+        if (restrictionBindings.size() == 1 && restrictionBindings.iterator().next().size() == 0) {
+            return listResults(pcjId);
+        }
+
+        final Document query = new Document(PCJ_ID, pcjId);
+        final Document bindingSetDoc = new Document();
+        final List<Document> bindingSetList = new ArrayList<>();
+        restrictionBindings.forEach(bindingSet -> {
+            final Document bindingDoc = new Document();
+            final List<Document> bindings = new ArrayList<>();
+            bindingSet.forEach(binding -> {
+                final RyaType type = RdfToRyaConversions.convertValue(binding.getValue());
+                final Document typeDoc = new Document()
+                        .append(BINDING_TYPE, type.getDataType().stringValue())
+                        .append(BINDING_VALUE, type.getData());
+                final Document bind = new Document(binding.getName(), typeDoc);
+                bindings.add(bind);
+            });
+            bindingDoc.append("$and", bindings);
+            bindingSetList.add(bindingDoc);
+        });
+        bindingSetDoc.append("$or", bindingSetList);
+        return queryForBindings(query);
+    }
+
+    private CloseableIterator<BindingSet> queryForBindings(final Document query) {
+        final FindIterable<Document> rez = pcjCollection.find(query);
+        final Iterator<Document> resultsIter = rez.iterator();
+        return new CloseableIterator<BindingSet>() {
+            @Override
+            public boolean hasNext() {
+                return resultsIter.hasNext();
+            }
+
+            @Override
+            public BindingSet next() {
+                final Document bs = resultsIter.next();
+                final MapBindingSet binding = new MapBindingSet();
+                for (final String key : bs.keySet()) {
+                    if (key.equals(VISIBILITIES_FIELD)) {
+                        // has auths, is a visibility binding set.
+                    } else if (!key.equals("_id") && !key.equals(PCJ_ID)) {
+                        // is the binding value.
+                        final Document typeDoc = (Document) bs.get(key);
+                        final URI dataType = new URIImpl(typeDoc.getString(BINDING_TYPE));
+                        final RyaType type = new RyaType(dataType, typeDoc.getString(BINDING_VALUE));
+                        final Value value = RyaToRdfConversions.convertValue(type);
+                        binding.addBinding(key, value);
+                    }
+                }
+                return binding;
+            }
+
+            @Override
+            public void close() throws Exception {
+            }
+        };
+    }
+
+    /**
+     * Drops a pcj based on the PCJ Id. Removing the entire document from Mongo.
+     *
+     * @param pcjId - The identifier for the PCJ to remove.
+     */
+    public void dropPcj(final String pcjId) {
+        purgePcjs(pcjId);
+        pcjCollection.deleteOne(new Document(PCJ_METADATA_ID, makeMetadataID(pcjId)));
+    }
+}
\ No newline at end of file



[6/8] incubator-rya git commit: RYA-303 Mongo PCJ Support. Closes #172.

Posted by ca...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoBatchUpdatePCJIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoBatchUpdatePCJIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoBatchUpdatePCJIT.java
new file mode 100644
index 0000000..7933374
--- /dev/null
+++ b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoBatchUpdatePCJIT.java
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+package org.apache.rya.api.client.mongo;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.rya.api.client.Install.InstallConfiguration;
+import org.apache.rya.api.client.RyaClient;
+import org.apache.rya.api.client.accumulo.AccumuloBatchUpdatePCJ;
+import org.apache.rya.api.utils.CloseableIterator;
+import org.apache.rya.indexing.accumulo.ConfigUtils;
+import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType;
+import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinUpdaterType;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjStorage;
+import org.apache.rya.mongodb.MongoDBRdfConfiguration;
+import org.apache.rya.mongodb.MongoITBase;
+import org.junit.Test;
+import org.openrdf.model.Statement;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.model.impl.ValueFactoryImpl;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.impl.MapBindingSet;
+
+/**
+ * Integration tests the methods of {@link AccumuloBatchUpdatePCJ}.
+ */
+public class MongoBatchUpdatePCJIT extends MongoITBase {
+
+    @Override
+    protected void updateConfiguration(final MongoDBRdfConfiguration conf) {
+        conf.setBoolean(ConfigUtils.USE_PCJ, true);
+        conf.set(ConfigUtils.PCJ_STORAGE_TYPE, PrecomputedJoinStorageType.MONGO.toString());
+        conf.set(ConfigUtils.PCJ_UPDATER_TYPE, PrecomputedJoinUpdaterType.NO_UPDATE.toString());
+    }
+
+
+    @Test
+    public void batchUpdate() throws Exception {
+        // Setup a Rya Client.
+        final MongoConnectionDetails connectionDetails = getConnectionDetails();
+        final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, getMongoClient());
+
+        // Install an instance of Rya on the mini accumulo cluster.
+        ryaClient.getInstall().install(conf.getRyaInstanceName(), InstallConfiguration.builder()
+                .setEnablePcjIndex(true)
+                .build());
+
+        // Load some statements into the Rya instance.
+        final ValueFactory vf = ValueFactoryImpl.getInstance();
+        final Collection<Statement> statements = new ArrayList<>();
+        statements.add(vf.createStatement(vf.createURI("urn:Alice"), vf.createURI("urn:likes"), vf.createURI("urn:icecream")));
+        statements.add(vf.createStatement(vf.createURI("urn:Bob"), vf.createURI("urn:likes"), vf.createURI("urn:icecream")));
+        statements.add(vf.createStatement(vf.createURI("urn:Charlie"), vf.createURI("urn:likes"), vf.createURI("urn:icecream")));
+        statements.add(vf.createStatement(vf.createURI("urn:David"), vf.createURI("urn:likes"), vf.createURI("urn:icecream")));
+        statements.add(vf.createStatement(vf.createURI("urn:Eve"), vf.createURI("urn:likes"), vf.createURI("urn:icecream")));
+        statements.add(vf.createStatement(vf.createURI("urn:Frank"), vf.createURI("urn:likes"), vf.createURI("urn:icecream")));
+        statements.add(vf.createStatement(vf.createURI("urn:George"), vf.createURI("urn:likes"), vf.createURI("urn:icecream")));
+        statements.add(vf.createStatement(vf.createURI("urn:Hillary"), vf.createURI("urn:likes"), vf.createURI("urn:icecream")));
+
+        statements.add(vf.createStatement(vf.createURI("urn:Alice"), vf.createURI("urn:hasEyeColor"), vf.createURI("urn:blue")));
+        statements.add(vf.createStatement(vf.createURI("urn:Bob"), vf.createURI("urn:hasEyeColor"), vf.createURI("urn:blue")));
+        statements.add(vf.createStatement(vf.createURI("urn:Charlie"), vf.createURI("urn:hasEyeColor"), vf.createURI("urn:blue")));
+        statements.add(vf.createStatement(vf.createURI("urn:David"), vf.createURI("urn:hasEyeColor"), vf.createURI("urn:blue")));
+        statements.add(vf.createStatement(vf.createURI("urn:Eve"), vf.createURI("urn:hasEyeColor"), vf.createURI("urn:blue")));
+        statements.add(vf.createStatement(vf.createURI("urn:Frank"), vf.createURI("urn:hasEyeColor"), vf.createURI("urn:blue")));
+        statements.add(vf.createStatement(vf.createURI("urn:George"), vf.createURI("urn:hasEyeColor"), vf.createURI("urn:green")));
+        statements.add(vf.createStatement(vf.createURI("urn:Hillary"), vf.createURI("urn:hasEyeColor"), vf.createURI("urn:brown")));
+        ryaClient.getLoadStatements().loadStatements(conf.getRyaInstanceName(), statements);
+
+        try(final PrecomputedJoinStorage pcjStorage = new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            // Create a PCJ for a SPARQL query.
+            final String sparql = "SELECT ?name WHERE { ?name <urn:likes> <urn:icecream> . ?name <urn:hasEyeColor> <urn:blue> . }";
+            final String pcjId = pcjStorage.createPcj(sparql);
+
+            // Run the test.
+            ryaClient.getBatchUpdatePCJ().batchUpdate(conf.getRyaInstanceName(), pcjId);
+
+            // Verify the correct results were loaded into the PCJ table.
+            final Set<BindingSet> expectedResults = new HashSet<>();
+
+            MapBindingSet bs = new MapBindingSet();
+            bs.addBinding("name", vf.createURI("urn:Alice"));
+            expectedResults.add(bs);
+
+            bs = new MapBindingSet();
+            bs.addBinding("name", vf.createURI("urn:Bob"));
+            expectedResults.add(bs);
+
+            bs = new MapBindingSet();
+            bs.addBinding("name", vf.createURI("urn:Charlie"));
+            expectedResults.add(bs);
+
+            bs = new MapBindingSet();
+            bs.addBinding("name", vf.createURI("urn:David"));
+            expectedResults.add(bs);
+
+            bs = new MapBindingSet();
+            bs.addBinding("name", vf.createURI("urn:Eve"));
+            expectedResults.add(bs);
+
+            bs = new MapBindingSet();
+            bs.addBinding("name", vf.createURI("urn:Frank"));
+            expectedResults.add(bs);
+
+            final Set<BindingSet> results = new HashSet<>();
+            try(CloseableIterator<BindingSet> resultsIt = pcjStorage.listResults(pcjId)) {
+                while(resultsIt.hasNext()) {
+                    results.add( resultsIt.next() );
+                }
+            }
+            assertEquals(expectedResults, results);
+        }
+    }
+
+    private MongoConnectionDetails getConnectionDetails() {
+        final java.util.Optional<char[]> password = conf.getMongoPassword() != null ?
+                java.util.Optional.of(conf.getMongoPassword().toCharArray()) :
+                    java.util.Optional.empty();
+
+                return new MongoConnectionDetails(
+                        conf.getMongoHostname(),
+                        Integer.parseInt(conf.getMongoPort()),
+                        java.util.Optional.ofNullable(conf.getMongoUser()),
+                        password);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoCreatePCJIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoCreatePCJIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoCreatePCJIT.java
new file mode 100644
index 0000000..183c195
--- /dev/null
+++ b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoCreatePCJIT.java
@@ -0,0 +1,122 @@
+/**
+ * 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.
+ */
+package org.apache.rya.api.client.mongo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.apache.rya.api.client.CreatePCJ;
+import org.apache.rya.api.client.Install;
+import org.apache.rya.api.client.Install.DuplicateInstanceNameException;
+import org.apache.rya.api.client.Install.InstallConfiguration;
+import org.apache.rya.api.client.InstanceDoesNotExistException;
+import org.apache.rya.api.client.RyaClient;
+import org.apache.rya.api.client.RyaClientException;
+import org.apache.rya.api.client.accumulo.AccumuloCreatePCJ;
+import org.apache.rya.api.instance.RyaDetails;
+import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.PCJDetails;
+import org.apache.rya.indexing.pcj.storage.PcjMetadata;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjStorage;
+import org.apache.rya.mongodb.MongoITBase;
+import org.junit.Test;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Integration tests the methods of {@link AccumuloCreatePCJ}.
+ */
+public class MongoCreatePCJIT extends MongoITBase {
+    @Test(expected = InstanceDoesNotExistException.class)
+    public void instanceDoesNotExist() throws Exception {
+        final RyaClient ryaClient = MongoRyaClientFactory.build(getConnectionDetails(), getMongoClient());
+        // Skip the install step to create error causing situation.
+        ryaClient.getCreatePCJ().createPCJ(conf.getRyaInstanceName(), "");
+    }
+
+    @Test
+    public void createPCJ() throws Exception {
+        final MongoConnectionDetails connectionDetails = getConnectionDetails();
+        final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, getMongoClient());
+        // Initialize the commands that will be used by this test.
+        final CreatePCJ createPCJ = ryaClient.getCreatePCJ();
+        final Install installRya = ryaClient.getInstall();
+        final InstallConfiguration installConf = InstallConfiguration.builder()
+                .setEnablePcjIndex(true)
+                .build();
+        installRya.install(conf.getRyaInstanceName(), installConf);
+
+        System.out.println(getMongoClient().getDatabase(conf.getRyaInstanceName()).getCollection("instance_details").find().first().toJson());
+        // Create a PCJ.
+        final String sparql =
+                "SELECT ?x " +
+                        "WHERE { " +
+                        "?x <http://talksTo> <http://Eve>. " +
+                        "?x <http://worksAt> <http://TacoJoint>." +
+                        "}";
+        final String pcjId = createPCJ.createPCJ(conf.getRyaInstanceName(), sparql);
+
+        // Verify the RyaDetails were updated to include the new PCJ.
+        final Optional<RyaDetails> ryaDetails = ryaClient.getGetInstanceDetails().getDetails(conf.getRyaInstanceName());
+        final ImmutableMap<String, PCJDetails> details = ryaDetails.get().getPCJIndexDetails().getPCJDetails();
+        final PCJDetails pcjDetails = details.get(pcjId);
+
+        assertEquals(pcjId, pcjDetails.getId());
+        assertFalse( pcjDetails.getLastUpdateTime().isPresent() );
+
+        // Verify the PCJ's metadata was initialized.
+
+        try(final PrecomputedJoinStorage pcjStorage = new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            final PcjMetadata pcjMetadata = pcjStorage.getPcjMetadata(pcjId);
+            //confirm that the pcj was added to the pcj store.
+            assertEquals(sparql, pcjMetadata.getSparql());
+            assertEquals(0L, pcjMetadata.getCardinality());
+        }
+    }
+
+    private MongoConnectionDetails getConnectionDetails() {
+        final java.util.Optional<char[]> password = conf.getMongoPassword() != null ?
+                java.util.Optional.of(conf.getMongoPassword().toCharArray()) :
+                    java.util.Optional.empty();
+
+                return new MongoConnectionDetails(
+                        conf.getMongoHostname(),
+                        Integer.parseInt(conf.getMongoPort()),
+                        java.util.Optional.ofNullable(conf.getMongoUser()),
+                        password);
+    }
+
+    @Test(expected = RyaClientException.class)
+    public void createPCJ_invalidSparql() throws DuplicateInstanceNameException, RyaClientException {
+        final MongoConnectionDetails connectionDetails = getConnectionDetails();
+        final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, getMongoClient());
+        // Initialize the commands that will be used by this test.
+        final CreatePCJ createPCJ = ryaClient.getCreatePCJ();
+        final Install installRya = ryaClient.getInstall();
+        final InstallConfiguration installConf = InstallConfiguration.builder()
+                .setEnablePcjIndex(true)
+                .build();
+        installRya.install(conf.getRyaInstanceName(), installConf);
+
+        // Create a PCJ.
+        final String sparql = "not valid sparql";
+        createPCJ.createPCJ(conf.getRyaInstanceName(), sparql);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoDeletePCJIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoDeletePCJIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoDeletePCJIT.java
new file mode 100644
index 0000000..d8137bc
--- /dev/null
+++ b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoDeletePCJIT.java
@@ -0,0 +1,93 @@
+/**
+ * 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.
+ */
+package org.apache.rya.api.client.mongo;
+
+import static org.junit.Assert.assertNull;
+
+import org.apache.rya.api.client.CreatePCJ;
+import org.apache.rya.api.client.DeletePCJ;
+import org.apache.rya.api.client.Install;
+import org.apache.rya.api.client.Install.InstallConfiguration;
+import org.apache.rya.api.client.InstanceDoesNotExistException;
+import org.apache.rya.api.client.RyaClient;
+import org.apache.rya.api.client.accumulo.AccumuloCreatePCJ;
+import org.apache.rya.api.instance.RyaDetails;
+import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.PCJDetails;
+import org.apache.rya.mongodb.MongoITBase;
+import org.junit.Test;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Integration tests the methods of {@link AccumuloCreatePCJ}.
+ */
+public class MongoDeletePCJIT extends MongoITBase {
+    @Test(expected = InstanceDoesNotExistException.class)
+    public void instanceDoesNotExist() throws Exception {
+        final RyaClient ryaClient = MongoRyaClientFactory.build(getConnectionDetails(), getMongoClient());
+        // Skip the install step to create error causing situation.
+        ryaClient.getDeletePCJ().deletePCJ(conf.getRyaInstanceName(), "doesn't matter, should fail before the pcjID is needed");
+    }
+
+    @Test
+    public void deletePCJ() throws Exception {
+        final MongoConnectionDetails connectionDetails = getConnectionDetails();
+        final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, getMongoClient());
+        // Initialize the commands that will be used by this test.
+        final CreatePCJ createPCJ = ryaClient.getCreatePCJ();
+        final Install installRya = ryaClient.getInstall();
+        final InstallConfiguration installConf = InstallConfiguration.builder()
+                .setEnablePcjIndex(true)
+                .build();
+        installRya.install(conf.getRyaInstanceName(), installConf);
+
+        System.out.println(getMongoClient().getDatabase(conf.getRyaInstanceName()).getCollection("instance_details").find().first().toJson());
+        // Create a PCJ.
+        final String sparql =
+                "SELECT ?x " +
+                        "WHERE { " +
+                        "?x <http://talksTo> <http://Eve>. " +
+                        "?x <http://worksAt> <http://TacoJoint>." +
+                        "}";
+        final String pcjId = createPCJ.createPCJ(conf.getRyaInstanceName(), sparql);
+
+        final DeletePCJ deletePCJ = ryaClient.getDeletePCJ();
+        deletePCJ.deletePCJ(conf.getRyaInstanceName(), pcjId);
+
+        // Verify the RyaDetails were updated to include the new PCJ.
+        final Optional<RyaDetails> ryaDetails = ryaClient.getGetInstanceDetails().getDetails(conf.getRyaInstanceName());
+        final ImmutableMap<String, PCJDetails> details = ryaDetails.get().getPCJIndexDetails().getPCJDetails();
+        final PCJDetails pcjDetails = details.get(pcjId);
+
+        assertNull(pcjDetails);
+    }
+
+    private MongoConnectionDetails getConnectionDetails() {
+        final java.util.Optional<char[]> password = conf.getMongoPassword() != null ?
+                java.util.Optional.of(conf.getMongoPassword().toCharArray()) :
+                    java.util.Optional.empty();
+
+                return new MongoConnectionDetails(
+                        conf.getMongoHostname(),
+                        Integer.parseInt(conf.getMongoPort()),
+                        java.util.Optional.ofNullable(conf.getMongoUser()),
+                        password);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoGetInstanceDetailsIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoGetInstanceDetailsIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoGetInstanceDetailsIT.java
index b3d96f6..5f1d222 100644
--- a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoGetInstanceDetailsIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoGetInstanceDetailsIT.java
@@ -84,7 +84,7 @@ public class MongoGetInstanceDetailsIT extends MongoITBase {
                 // PCJJ Index is not supported, so it flips to false.
                 .setPCJIndexDetails(
                         PCJIndexDetails.builder()
-                        .setEnabled(false))
+                        .setEnabled(true))
 
                 .setProspectorDetails( new ProspectorDetails(Optional.<Date>absent()) )
                 .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.<Date>absent()) )
@@ -119,10 +119,10 @@ public class MongoGetInstanceDetailsIT extends MongoITBase {
                 java.util.Optional.of(conf.getMongoPassword().toCharArray()) :
                     java.util.Optional.empty();
 
-        return new MongoConnectionDetails(
-                conf.getMongoHostname(),
-                Integer.parseInt(conf.getMongoPort()),
-                java.util.Optional.ofNullable(conf.getMongoUser()),
-                password);
+                return new MongoConnectionDetails(
+                        conf.getMongoHostname(),
+                        Integer.parseInt(conf.getMongoPort()),
+                        java.util.Optional.ofNullable(conf.getMongoUser()),
+                        password);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoInstallIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoInstallIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoInstallIT.java
index e3df916..ecca646 100644
--- a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoInstallIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoInstallIT.java
@@ -79,6 +79,47 @@ public class MongoInstallIT extends MongoITBase {
         assertTrue("Instance should exist.", instanceExists.exists(ryaInstance));
     }
 
+    @Test
+    public void install_withAllIndexers() throws DuplicateInstanceNameException, RyaClientException {
+        // Install an instance of Rya.
+        final String ryaInstance = conf.getMongoDBName();
+
+        // Setup the connection details that were used for the embedded Mongo DB instance we are testing with.
+        final MongoConnectionDetails connectionDetails = getConnectionDetails();
+
+        // Check that the instance does not exist.
+        final InstanceExists instanceExists = new MongoInstanceExists(getMongoClient());
+        assertFalse(instanceExists.exists(ryaInstance));
+
+        // Install an instance of Rya with all the valid options turned on.
+        final InstallConfiguration installConfig = InstallConfiguration.builder()
+                .setEnableTableHashPrefix(true)
+                .setEnableFreeTextIndex(true)
+                .setEnableTemporalIndex(true)
+                .setEnableEntityCentricIndex(true)
+                .setEnableGeoIndex(true)
+                .setEnablePcjIndex(true)
+                .build();
+
+        final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, getMongoClient());
+        final Install install = ryaClient.getInstall();
+        install.install(ryaInstance, installConfig);
+
+        // Check that the instance exists.
+        assertTrue(instanceExists.exists(ryaInstance));
+
+        // Show that the expected collections were created within the database.
+        final List<String> expected = Arrays.asList(INSTANCE_DETAILS_COLLECTION_NAME, "rya_triples");
+        int count = 0;
+        final List<String> found = new ArrayList<>();
+        for (final String collection : getMongoClient().getDatabase(conf.getMongoDBName()).listCollectionNames()) {
+            count += expected.contains(collection) ? 1 : 0;
+            found.add( collection );
+        }
+        assertTrue("Tables missing from:" + expected + " actual:" + found, expected.size() == count);
+        assertTrue("Instance should exist.", instanceExists.exists(ryaInstance));
+    }
+
     @Test(expected = DuplicateInstanceNameException.class)
     public void install_alreadyExists() throws DuplicateInstanceNameException, RyaClientException {
         // Install an instance of Rya.
@@ -100,10 +141,10 @@ public class MongoInstallIT extends MongoITBase {
                 Optional.of(conf.getMongoPassword().toCharArray()) :
                     Optional.empty();
 
-        return new MongoConnectionDetails(
-                conf.getMongoHostname(),
-                Integer.parseInt(conf.getMongoPort()),
-                Optional.ofNullable(conf.getMongoUser()),
-                password);
+                return new MongoConnectionDetails(
+                        conf.getMongoHostname(),
+                        Integer.parseInt(conf.getMongoPort()),
+                        Optional.ofNullable(conf.getMongoUser()),
+                        password);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/IndexPlanValidatorTest.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/IndexPlanValidatorTest.java b/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/IndexPlanValidatorTest.java
index ffd6691..d54523c 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/IndexPlanValidatorTest.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/IndexPlanValidatorTest.java
@@ -1,6 +1,4 @@
-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
@@ -18,18 +16,26 @@ package org.apache.rya.indexing.IndexPlanValidator;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.rya.indexing.IndexPlanValidator;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
+import org.apache.rya.indexing.mongodb.pcj.MongoPcjIndexSetProvider;
 import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
-
+import org.apache.rya.indexing.pcj.matching.provider.AbstractPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
+import org.apache.rya.mongodb.EmbeddedMongoSingleton;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
 import org.junit.Assert;
 import org.junit.Test;
-import org.openrdf.query.MalformedQueryException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 import org.openrdf.query.algebra.Projection;
 import org.openrdf.query.algebra.TupleExpr;
 import org.openrdf.query.parser.ParsedQuery;
@@ -37,716 +43,743 @@ import org.openrdf.query.parser.sparql.SPARQLParser;
 
 import com.google.common.collect.Lists;
 
+@RunWith(Parameterized.class)
 public class IndexPlanValidatorTest {
+    private final AbstractPcjIndexSetProvider provider;
+
+    @Parameterized.Parameters
+    public static Collection providers() throws Exception {
+        final StatefulMongoDBRdfConfiguration conf = new StatefulMongoDBRdfConfiguration(new Configuration(), EmbeddedMongoSingleton.getNewMongoClient());
+        return Lists.<AbstractPcjIndexSetProvider> newArrayList(
+                new AccumuloIndexSetProvider(new Configuration()),
+                new MongoPcjIndexSetProvider(conf)
+                );
+    }
+
+    public IndexPlanValidatorTest(final AbstractPcjIndexSetProvider provider) {
+        this.provider = provider;
+    }
+
+    @Test
+    public void testEvaluateTwoIndexTwoVarOrder1()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?c ?e ?l  " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?e ?o ?l " //
+                + "{" //
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(false, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexTwoVarOrder2()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?e ?l ?c  " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?e ?o ?l " //
+                + "{" //
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(true, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexTwoVarOrder3()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?l ?e ?c  " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?e ?o ?l " //
+                + "{" //
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
 
-	@Test
-	public void testEvaluateTwoIndexTwoVarOrder1()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?c ?e ?l  " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?e ?o ?l " //
-				+ "{" //
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(false, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexTwoVarOrder2()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?e ?l ?c  " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?e ?o ?l " //
-				+ "{" //
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(true, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexTwoVarOrder3()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?l ?e ?c  " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?e ?o ?l " //
-				+ "{" //
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(true, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexTwoVarOrder4()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?e ?c ?l  " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?e ?o ?l " //
-				+ "{" //
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
 
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(true, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexTwoVarOrder4()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?e ?c ?l  " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?e ?o ?l " //
+                + "{" //
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
 
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(false, ipv.isValid(tup));
-
-	}
-
-
-	@Test
-	public void testEvaluateTwoIndexTwoVarOrder6()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?e ?l ?c  " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
 
-		String indexSparqlString2 = ""//
-				+ "SELECT ?l ?e ?o " //
-				+ "{" //
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(false, ipv.isValid(tup));
+
+    }
+
+
+    @Test
+    public void testEvaluateTwoIndexTwoVarOrder6()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?e ?l ?c  " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?l ?e ?o " //
+                + "{" //
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
 
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais2);
-		index.add(ais1);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(true, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexCrossProduct1()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?e ?l ?c  " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?e ?l ?o " //
-				+ "{" //
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o ?f ?g " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?f <uri:talksTo> ?g . " //
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais2);
-		index.add(ais1);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-		IndexPlanValidator ipv = new IndexPlanValidator(true);
-		Assert.assertEquals(false, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexCrossProduct2()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?e ?l ?c  " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?e ?l ?o " //
-				+ "{" //
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o ?f ?g " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?f <uri:talksTo> ?g . " //
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-		IndexPlanValidator ipv = new IndexPlanValidator(true);
-		Assert.assertEquals(false, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexCrossProduct3()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?e ?l ?c  " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?e ?l ?o " //
-				+ "{" //
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o ?f ?g " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?f <uri:talksTo> ?g . " //
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(true, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexDiffVars() throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?chicken ?dog ?pig  " //
-				+ "{" //
-				+ "  ?dog a ?chicken . "//
-				+ "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?fish ?ant ?turkey " //
-				+ "{" //
-				+ "  ?fish <uri:talksTo> ?turkey . "//
-				+ "  ?turkey <http://www.w3.org/2000/01/rdf-schema#label> ?ant "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o ?f ?g " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?f <uri:talksTo> ?g . " //
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(false, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexDiffVars2() throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?dog ?pig ?chicken  " //
-				+ "{" //
-				+ "  ?dog a ?chicken . "//
-				+ "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?fish ?ant ?turkey " //
-				+ "{" //
-				+ "  ?fish <uri:talksTo> ?turkey . "//
-				+ "  ?turkey <http://www.w3.org/2000/01/rdf-schema#label> ?ant "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o ?f ?g " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?f <uri:talksTo> ?g . " //
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(true, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexDiffVars3() throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?pig ?dog ?chicken  " //
-				+ "{" //
-				+ "  ?dog a ?chicken . "//
-				+ "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?fish ?ant ?turkey " //
-				+ "{" //
-				+ "  ?fish <uri:talksTo> ?turkey . "//
-				+ "  ?turkey <http://www.w3.org/2000/01/rdf-schema#label> ?ant "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o ?f ?g " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?f <uri:talksTo> ?g . " //
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-		IndexPlanValidator ipv = new IndexPlanValidator(false);
-		Assert.assertEquals(true, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testEvaluateTwoIndexDiffVarsDirProd()
-			throws Exception {
-
-
-		String indexSparqlString = ""//
-				+ "SELECT ?pig ?dog ?chicken  " //
-				+ "{" //
-				+ "  ?dog a ?chicken . "//
-				+ "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig "//
-				+ "}";//
-
-		String indexSparqlString2 = ""//
-				+ "SELECT ?fish ?ant ?turkey " //
-				+ "{" //
-				+ "  ?fish <uri:talksTo> ?turkey . "//
-				+ "  ?turkey <http://www.w3.org/2000/01/rdf-schema#label> ?ant "//
-				+ "}";//
-
-		String queryString = ""//
-				+ "SELECT ?e ?c ?l ?o ?f ?g " //
-				+ "{" //
-				+ "  ?e a ?c . "//
-				+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?e <uri:talksTo> ?o . "//
-				+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-				+ "  ?f <uri:talksTo> ?g . " //
-				+ "}";//
-
-		SPARQLParser sp = new SPARQLParser();
-		ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
-		ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
-
-		List<ExternalTupleSet> index = Lists.newArrayList();
-
-		SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
-				(Projection) index1.getTupleExpr());
-		SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
-				(Projection) index2.getTupleExpr());
-
-		index.add(ais1);
-		index.add(ais2);
-
-		ParsedQuery pq = sp.parseQuery(queryString, null);
-		TupleExpr tup = pq.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(index, false);
-		pcj.optimize(tup, null, null);
-
-		IndexPlanValidator ipv = new IndexPlanValidator(true);
-		Assert.assertEquals(false, ipv.isValid(tup));
-
-	}
-
-	@Test
-	public void testValidTupleIterator() throws Exception {
-
-		String q1 = ""//
-				+ "SELECT ?f ?m ?d ?h ?i " //
-				+ "{" //
-				+ "  ?f a ?m ."//
-				+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-				+ "  ?d <uri:talksTo> ?f . "//
-				+ "  ?d <uri:hangOutWith> ?f ." //
-				+ "  ?f <uri:hangOutWith> ?h ." //
-				+ "  ?f <uri:associatesWith> ?i ." //
-				+ "  ?i <uri:associatesWith> ?h ." //
-				+ "}";//
-
-		String q2 = ""//
-				+ "SELECT ?t ?s ?u " //
-				+ "{" //
-				+ "  ?s a ?t ."//
-				+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-				+ "  ?u <uri:talksTo> ?s . "//
-				+ "}";//
-
-		String q3 = ""//
-				+ "SELECT ?s ?t ?u " //
-				+ "{" //
-				+ "  ?s <uri:hangOutWith> ?t ." //
-				+ "  ?t <uri:hangOutWith> ?u ." //
-				+ "}";//
-
-		String q4 = ""//
-				+ "SELECT ?s ?t ?u " //
-				+ "{" //
-				+ "  ?s <uri:associatesWith> ?t ." //
-				+ "  ?t <uri:associatesWith> ?u ." //
-				+ "}";//
-
-		SPARQLParser parser = new SPARQLParser();
-
-		ParsedQuery pq1 = parser.parseQuery(q1, null);
-		ParsedQuery pq2 = parser.parseQuery(q2, null);
-		ParsedQuery pq3 = parser.parseQuery(q3, null);
-		ParsedQuery pq4 = parser.parseQuery(q4, null);
-
-		SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-		SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				(Projection) pq3.getTupleExpr());
-		SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				(Projection) pq4.getTupleExpr());
-
-		List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-
-		list.add(extTup2);
-		list.add(extTup1);
-		list.add(extTup3);
-
-		IndexedExecutionPlanGenerator iep = new IndexedExecutionPlanGenerator(
-				pq1.getTupleExpr(), list);
-
-		Iterator<TupleExpr> plans = new TupleExecutionPlanGenerator()
-				.getPlans(iep.getIndexedTuples());
-		IndexPlanValidator ipv = new IndexPlanValidator(true);
-		Iterator<TupleExpr> validPlans = ipv.getValidTuples(plans);
-
-		int size = 0;
-
-		while (validPlans.hasNext()) {
-			Assert.assertTrue(validPlans.hasNext());
-			validPlans.next();
-			size++;
-		}
-
-		Assert.assertTrue(!validPlans.hasNext());
-		Assert.assertEquals(732, size);
-
-	}
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais2);
+        index.add(ais1);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(true, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexCrossProduct1()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?e ?l ?c  " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?e ?l ?o " //
+                + "{" //
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o ?f ?g " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?f <uri:talksTo> ?g . " //
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais2);
+        index.add(ais1);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(true);
+        Assert.assertEquals(false, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexCrossProduct2()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?e ?l ?c  " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?e ?l ?o " //
+                + "{" //
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o ?f ?g " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?f <uri:talksTo> ?g . " //
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(true);
+        Assert.assertEquals(false, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexCrossProduct3()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?e ?l ?c  " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?e ?l ?o " //
+                + "{" //
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o ?f ?g " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?f <uri:talksTo> ?g . " //
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(true, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexDiffVars() throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?chicken ?dog ?pig  " //
+                + "{" //
+                + "  ?dog a ?chicken . "//
+                + "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?fish ?ant ?turkey " //
+                + "{" //
+                + "  ?fish <uri:talksTo> ?turkey . "//
+                + "  ?turkey <http://www.w3.org/2000/01/rdf-schema#label> ?ant "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o ?f ?g " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?f <uri:talksTo> ?g . " //
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(false, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexDiffVars2() throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?dog ?pig ?chicken  " //
+                + "{" //
+                + "  ?dog a ?chicken . "//
+                + "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?fish ?ant ?turkey " //
+                + "{" //
+                + "  ?fish <uri:talksTo> ?turkey . "//
+                + "  ?turkey <http://www.w3.org/2000/01/rdf-schema#label> ?ant "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o ?f ?g " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?f <uri:talksTo> ?g . " //
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(true, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexDiffVars3() throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?pig ?dog ?chicken  " //
+                + "{" //
+                + "  ?dog a ?chicken . "//
+                + "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?fish ?ant ?turkey " //
+                + "{" //
+                + "  ?fish <uri:talksTo> ?turkey . "//
+                + "  ?turkey <http://www.w3.org/2000/01/rdf-schema#label> ?ant "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o ?f ?g " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?f <uri:talksTo> ?g . " //
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(false);
+        Assert.assertEquals(true, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testEvaluateTwoIndexDiffVarsDirProd()
+            throws Exception {
+
+
+        final String indexSparqlString = ""//
+                + "SELECT ?pig ?dog ?chicken  " //
+                + "{" //
+                + "  ?dog a ?chicken . "//
+                + "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig "//
+                + "}";//
+
+        final String indexSparqlString2 = ""//
+                + "SELECT ?fish ?ant ?turkey " //
+                + "{" //
+                + "  ?fish <uri:talksTo> ?turkey . "//
+                + "  ?turkey <http://www.w3.org/2000/01/rdf-schema#label> ?ant "//
+                + "}";//
+
+        final String queryString = ""//
+                + "SELECT ?e ?c ?l ?o ?f ?g " //
+                + "{" //
+                + "  ?e a ?c . "//
+                + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?e <uri:talksTo> ?o . "//
+                + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+                + "  ?f <uri:talksTo> ?g . " //
+                + "}";//
+
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedQuery index1 = sp.parseQuery(indexSparqlString, null);
+        final ParsedQuery index2 = sp.parseQuery(indexSparqlString2, null);
+
+        final List<ExternalTupleSet> index = Lists.newArrayList();
+
+        final SimpleExternalTupleSet ais1 = new SimpleExternalTupleSet(
+                (Projection) index1.getTupleExpr());
+        final SimpleExternalTupleSet ais2 = new SimpleExternalTupleSet(
+                (Projection) index2.getTupleExpr());
+
+        index.add(ais1);
+        index.add(ais2);
+
+        final ParsedQuery pq = sp.parseQuery(queryString, null);
+        final TupleExpr tup = pq.getTupleExpr().clone();
+        provider.setIndices(index);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final IndexPlanValidator ipv = new IndexPlanValidator(true);
+        Assert.assertEquals(false, ipv.isValid(tup));
+
+    }
+
+    @Test
+    public void testValidTupleIterator() throws Exception {
+
+        final String q1 = ""//
+                + "SELECT ?f ?m ?d ?h ?i " //
+                + "{" //
+                + "  ?f a ?m ."//
+                + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+                + "  ?d <uri:talksTo> ?f . "//
+                + "  ?d <uri:hangOutWith> ?f ." //
+                + "  ?f <uri:hangOutWith> ?h ." //
+                + "  ?f <uri:associatesWith> ?i ." //
+                + "  ?i <uri:associatesWith> ?h ." //
+                + "}";//
+
+        final String q2 = ""//
+                + "SELECT ?t ?s ?u " //
+                + "{" //
+                + "  ?s a ?t ."//
+                + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+                + "  ?u <uri:talksTo> ?s . "//
+                + "}";//
+
+        final String q3 = ""//
+                + "SELECT ?s ?t ?u " //
+                + "{" //
+                + "  ?s <uri:hangOutWith> ?t ." //
+                + "  ?t <uri:hangOutWith> ?u ." //
+                + "}";//
+
+        final String q4 = ""//
+                + "SELECT ?s ?t ?u " //
+                + "{" //
+                + "  ?s <uri:associatesWith> ?t ." //
+                + "  ?t <uri:associatesWith> ?u ." //
+                + "}";//
+
+        final SPARQLParser parser = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser.parseQuery(q1, null);
+        final ParsedQuery pq2 = parser.parseQuery(q2, null);
+        final ParsedQuery pq3 = parser.parseQuery(q3, null);
+        final ParsedQuery pq4 = parser.parseQuery(q4, null);
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                (Projection) pq3.getTupleExpr());
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                (Projection) pq4.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+
+        list.add(extTup2);
+        list.add(extTup1);
+        list.add(extTup3);
+
+        final IndexedExecutionPlanGenerator iep = new IndexedExecutionPlanGenerator(
+                pq1.getTupleExpr(), list);
+
+        final Iterator<TupleExpr> plans = new TupleExecutionPlanGenerator()
+                .getPlans(iep.getIndexedTuples());
+        final IndexPlanValidator ipv = new IndexPlanValidator(true);
+        final Iterator<TupleExpr> validPlans = ipv.getValidTuples(plans);
+
+        int size = 0;
+
+        while (validPlans.hasNext()) {
+            Assert.assertTrue(validPlans.hasNext());
+            validPlans.next();
+            size++;
+        }
+
+        Assert.assertTrue(!validPlans.hasNext());
+        Assert.assertEquals(732, size);
+
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/ThreshholdPlanSelectorTest.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/ThreshholdPlanSelectorTest.java b/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/ThreshholdPlanSelectorTest.java
index b244a60..106288e 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/ThreshholdPlanSelectorTest.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/IndexPlanValidator/ThreshholdPlanSelectorTest.java
@@ -23,10 +23,11 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
 import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
-
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
 import org.junit.Assert;
 import org.junit.Test;
 import org.openrdf.query.algebra.Projection;
@@ -679,7 +680,7 @@ public class ThreshholdPlanSelectorTest {
 		eList.add(sep);
 
 		final TupleExpr te = pq1.getTupleExpr().clone();
-		final PCJOptimizer pcj = new PCJOptimizer(eList, false);
+		final PCJOptimizer pcj = new PCJOptimizer(eList, false, new AccumuloIndexSetProvider(new Configuration(), eList));
         pcj.optimize(te, null, null);
 
 		ThreshholdPlanSelector tps = new ThreshholdPlanSelector(

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloConstantPcjIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloConstantPcjIT.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloConstantPcjIT.java
index 8c55e98..5d53737 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloConstantPcjIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloConstantPcjIT.java
@@ -75,10 +75,10 @@ public class AccumuloConstantPcjIT {
 			TableNotFoundException, RyaDAOException, InferenceEngineException,
 			NumberFormatException, UnknownHostException, SailException {
 
-		repo = PcjIntegrationTestingUtil.getNonPcjRepo(prefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloNonPcjRepo(prefix, "instance");
 		conn = repo.getConnection();
 
-		pcjRepo = PcjIntegrationTestingUtil.getPcjRepo(prefix, "instance");
+		pcjRepo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(prefix, "instance");
 		pcjConn = pcjRepo.getConnection();
 
 		final URI sub = new URIImpl("uri:entity");

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloPcjIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloPcjIT.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloPcjIT.java
index 76560f8..d8a70aa 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloPcjIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/AccumuloPcjIT.java
@@ -34,8 +34,19 @@ import org.apache.accumulo.core.client.TableExistsException;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.admin.TableOperations;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.rya.accumulo.AccumuloRdfConfiguration;
+import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
+import org.apache.rya.api.persist.RyaDAOException;
+import org.apache.rya.indexing.IndexPlanValidator.IndexPlanValidator;
+import org.apache.rya.indexing.accumulo.ConfigUtils;
+import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType;
+import org.apache.rya.indexing.external.tupleSet.AccumuloIndexSet;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
 import org.apache.rya.indexing.pcj.storage.PcjException;
 import org.apache.rya.indexing.pcj.storage.accumulo.PcjVarOrderFactory;
+import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -64,17 +75,6 @@ import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
-import org.apache.rya.accumulo.AccumuloRdfConfiguration;
-import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
-import org.apache.rya.api.persist.RyaDAOException;
-import org.apache.rya.indexing.IndexPlanValidator.IndexPlanValidator;
-import org.apache.rya.indexing.accumulo.ConfigUtils;
-import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType;
-import org.apache.rya.indexing.external.tupleSet.AccumuloIndexSet;
-import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
-import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
-import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
-
 public class AccumuloPcjIT {
 
 	private SailRepositoryConnection conn, pcjConn;
@@ -93,10 +93,10 @@ public class AccumuloPcjIT {
 			TableNotFoundException, InferenceEngineException,
 			NumberFormatException, UnknownHostException, SailException {
 
-		repo = PcjIntegrationTestingUtil.getNonPcjRepo(prefix, "instance");
+		repo = PcjIntegrationTestingUtil.getAccumuloNonPcjRepo(prefix, "instance");
 		conn = repo.getConnection();
 
-		pcjRepo = PcjIntegrationTestingUtil.getPcjRepo(prefix, "instance");
+		pcjRepo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(prefix, "instance");
 		pcjConn = pcjRepo.getConnection();
 
 		final URI sub = new URIImpl("uri:entity");
@@ -1274,7 +1274,7 @@ public class AccumuloPcjIT {
 		final List<TupleExpr> teList = Lists.newArrayList();
 		final TupleExpr te = pq.getTupleExpr();
 
-		final PCJOptimizer pcj = new PCJOptimizer(index, false);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, new AccumuloIndexSetProvider(conf));
         pcj.optimize(te, null, null);
 		teList.add(te);
 
@@ -1372,7 +1372,7 @@ public class AccumuloPcjIT {
 		final List<TupleExpr> teList = Lists.newArrayList();
 		final TupleExpr te = pq.getTupleExpr();
 
-		final PCJOptimizer pcj = new PCJOptimizer(index, false);
+        final PCJOptimizer pcj = new PCJOptimizer(index, false, new AccumuloIndexSetProvider(conf));
         pcj.optimize(te, null, null);
 
 		teList.add(te);

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/external/PCJOptionalTestIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PCJOptionalTestIT.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PCJOptionalTestIT.java
index 732bc12..026fa34 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PCJOptionalTestIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PCJOptionalTestIT.java
@@ -29,8 +29,17 @@ import org.apache.accumulo.core.client.TableExistsException;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.mock.MockInstance;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.rya.api.persist.RyaDAOException;
+import org.apache.rya.indexing.external.PrecompJoinOptimizerIT.CountingResultHandler;
+import org.apache.rya.indexing.external.PrecompJoinOptimizerTest.NodeCollector;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
+import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
 import org.apache.rya.indexing.pcj.storage.PcjException;
 import org.apache.rya.indexing.pcj.storage.accumulo.PcjVarOrderFactory;
+import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -58,14 +67,6 @@ import org.openrdf.sail.SailException;
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 
-import org.apache.rya.api.persist.RyaDAOException;
-import org.apache.rya.indexing.external.PrecompJoinOptimizerIT.CountingResultHandler;
-import org.apache.rya.indexing.external.PrecompJoinOptimizerTest.NodeCollector;
-import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
-import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
-import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
-import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
-
 public class PCJOptionalTestIT {
 
 
@@ -83,10 +84,10 @@ public class PCJOptionalTestIT {
             TableNotFoundException, InferenceEngineException, NumberFormatException,
             UnknownHostException, SailException {
 
-        repo = PcjIntegrationTestingUtil.getNonPcjRepo(tablePrefix, "instance");
+        repo = PcjIntegrationTestingUtil.getAccumuloNonPcjRepo(tablePrefix, "instance");
         conn = repo.getConnection();
 
-        pcjRepo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+        pcjRepo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
         pcjConn = pcjRepo.getConnection();
 
         sub = new URIImpl("uri:entity");
@@ -196,7 +197,7 @@ public class PCJOptionalTestIT {
         PcjIntegrationTestingUtil.deleteCoreRyaTables(accCon, tablePrefix);
         PcjIntegrationTestingUtil.closeAndShutdown(conn, repo);
 
-        repo = PcjIntegrationTestingUtil.getPcjRepo(tablePrefix, "instance");
+        repo = PcjIntegrationTestingUtil.getAccumuloPcjRepo(tablePrefix, "instance");
         conn = repo.getConnection();
         conn.add(sub, RDF.TYPE, subclass);
         conn.add(sub2, RDF.TYPE, subclass2);
@@ -240,7 +241,7 @@ public class PCJOptionalTestIT {
         final List<QueryModelNode> optTupNodes = Lists.newArrayList();
         optTupNodes.add(extTup1);
 
-        final PCJOptimizer pcj = new PCJOptimizer(list, true);
+        final PCJOptimizer pcj = new PCJOptimizer(list, true, new AccumuloIndexSetProvider(new Configuration(), list));
         final TupleExpr te = pq1.getTupleExpr();
         pcj.optimize(te, null, null);
 
@@ -306,7 +307,7 @@ public class PCJOptionalTestIT {
         final List<QueryModelNode> optTupNodes = Lists.newArrayList();
         optTupNodes.add(extTup2);
 
-        final PCJOptimizer opt = new PCJOptimizer(list, true);
+        final PCJOptimizer opt = new PCJOptimizer(list, true, new AccumuloIndexSetProvider(new Configuration(), list));
         final TupleExpr te = pq1.getTupleExpr();
         opt.optimize(te, null, null);
 



[2/8] incubator-rya git commit: RYA-303 Mongo PCJ Support. Closes #172.

Posted by ca...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjStorage.java
----------------------------------------------------------------------
diff --git a/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjStorage.java b/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjStorage.java
new file mode 100644
index 0000000..f4e4e9e
--- /dev/null
+++ b/extras/rya.indexing.pcj/src/main/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjStorage.java
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+package org.apache.rya.indexing.pcj.storage.mongo;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.rya.api.instance.RyaDetails;
+import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails;
+import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.PCJDetails;
+import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException;
+import org.apache.rya.api.instance.RyaDetailsUpdater;
+import org.apache.rya.api.instance.RyaDetailsUpdater.RyaDetailsMutator.CouldNotApplyMutationException;
+import org.apache.rya.api.model.VisibilityBindingSet;
+import org.apache.rya.api.utils.CloseableIterator;
+import org.apache.rya.indexing.pcj.storage.PCJIdFactory;
+import org.apache.rya.indexing.pcj.storage.PcjMetadata;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage;
+import org.apache.rya.mongodb.instance.MongoRyaInstanceDetailsRepository;
+import org.openrdf.query.BindingSet;
+
+import com.mongodb.MongoClient;
+
+import edu.umd.cs.findbugs.annotations.DefaultAnnotation;
+import edu.umd.cs.findbugs.annotations.NonNull;
+
+/**
+ * A mongo backed implementation of {@link PrecomputedJoinStorage}.
+ */
+@DefaultAnnotation(NonNull.class)
+public class MongoPcjStorage implements PrecomputedJoinStorage {
+    public static final String PCJ_COLLECTION_NAME = "pcjs";
+    // Used to update the instance's metadata.
+    private final MongoRyaInstanceDetailsRepository ryaDetailsRepo;
+
+    private final String ryaInstanceName;
+
+    // Factories that are used to create new PCJs.
+    private final PCJIdFactory pcjIdFactory = new PCJIdFactory();
+
+    private final MongoPcjDocuments pcjDocs;
+
+    /**
+     * Constructs an instance of {@link MongoPcjStorage}.
+     *
+     * @param client - The {@link MongoClient} that will be used to connect to Mongodb. (not null)
+     * @param ryaInstanceName - The name of the RYA instance that will be accessed. (not null)
+     */
+    public MongoPcjStorage(final MongoClient client, final String ryaInstanceName) {
+        requireNonNull(client);
+        this.ryaInstanceName = requireNonNull(ryaInstanceName);
+        pcjDocs = new MongoPcjDocuments(client, ryaInstanceName);
+        ryaDetailsRepo = new MongoRyaInstanceDetailsRepository(client, ryaInstanceName);
+    }
+
+    @Override
+    public String createPcj(final String sparql) throws PCJStorageException {
+        requireNonNull(sparql);
+
+        // Update the Rya Details for this instance to include the new PCJ
+        // table.
+        final String pcjId = pcjIdFactory.nextId();
+
+        try {
+            new RyaDetailsUpdater(ryaDetailsRepo).update(originalDetails -> {
+                // Create the new PCJ's details.
+                final PCJDetails.Builder newPcjDetails = PCJDetails.builder().setId(pcjId);
+
+                // Add them to the instance's details.
+                final RyaDetails.Builder mutated = RyaDetails.builder(originalDetails);
+                mutated.getPCJIndexDetails().addPCJDetails(newPcjDetails);
+                return mutated.build();
+            });
+        } catch (final RyaDetailsRepositoryException | CouldNotApplyMutationException e) {
+            throw new PCJStorageException(String.format("Could not create a new PCJ for Rya instance '%s' "
+                    + "because of a problem while updating the instance's details.", ryaInstanceName), e);
+        }
+
+        // Create the objectID of the document to house the PCJ results.
+        pcjDocs.createPcj(pcjId, sparql);
+
+        // Add access to the PCJ table to all users who are authorized for this
+        // instance of Rya.
+        return pcjId;
+    }
+
+
+    @Override
+    public PcjMetadata getPcjMetadata(final String pcjId) throws PCJStorageException {
+        requireNonNull(pcjId);
+        return pcjDocs.getPcjMetadata(pcjId);
+    }
+
+    @Override
+    public void addResults(final String pcjId, final Collection<VisibilityBindingSet> results) throws PCJStorageException {
+        requireNonNull(pcjId);
+        requireNonNull(results);
+        pcjDocs.addResults(pcjId, results);
+    }
+
+
+    @Override
+    public CloseableIterator<BindingSet> listResults(final String pcjId) throws PCJStorageException {
+        requireNonNull(pcjId);
+        // Scan the PCJ table.
+        return pcjDocs.listResults(pcjId);
+    }
+
+    @Override
+    public void purge(final String pcjId) throws PCJStorageException {
+        requireNonNull(pcjId);
+        pcjDocs.purgePcjs(pcjId);
+    }
+
+    @Override
+    public void dropPcj(final String pcjId) throws PCJStorageException {
+        requireNonNull(pcjId);
+
+        // Update the Rya Details for this instance to no longer include the
+        // PCJ.
+        try {
+            new RyaDetailsUpdater(ryaDetailsRepo).update(originalDetails -> {
+                // Drop the PCJ's metadata from the instance's metadata.
+                final RyaDetails.Builder mutated = RyaDetails.builder(originalDetails);
+                mutated.getPCJIndexDetails().removePCJDetails(pcjId);
+                return mutated.build();
+            });
+        } catch (final RyaDetailsRepositoryException | CouldNotApplyMutationException e) {
+            throw new PCJStorageException(String.format("Could not drop an existing PCJ for Rya instance '%s' "
+                    + "because of a problem while updating the instance's details.", ryaInstanceName), e);
+        }
+
+        // Delete the table that hold's the PCJ's results.
+        pcjDocs.dropPcj(pcjId);
+    }
+
+    @Override
+    public List<String> listPcjs() throws PCJStorageException {
+        try {
+            final RyaDetails details = ryaDetailsRepo.getRyaInstanceDetails();
+            final PCJIndexDetails pcjIndexDetails = details.getPCJIndexDetails();
+            final List<String> pcjIds = new ArrayList<>(pcjIndexDetails.getPCJDetails().keySet());
+            return pcjIds;
+        } catch (final RyaDetailsRepositoryException e) {
+            throw new PCJStorageException("Could not check to see if RyaDetails exist for the instance.", e);
+        }
+    }
+
+    @Override
+    public void close() throws PCJStorageException {
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjDocumentsTest.java
----------------------------------------------------------------------
diff --git a/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjDocumentsTest.java b/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjDocumentsTest.java
new file mode 100644
index 0000000..f522fac
--- /dev/null
+++ b/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjDocumentsTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+package org.apache.rya.indexing.pcj.storage.mongo;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.rya.api.model.VisibilityBindingSet;
+import org.apache.rya.indexing.pcj.storage.PcjMetadata;
+import org.apache.rya.indexing.pcj.storage.accumulo.VariableOrder;
+import org.apache.rya.mongodb.MongoITBase;
+import org.bson.Document;
+import org.junit.Test;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.query.impl.MapBindingSet;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class MongoPcjDocumentsTest extends MongoITBase {
+    @Test
+    public void pcjToMetadata() throws Exception {
+        final MongoPcjDocuments docConverter = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+        final String sparql = "SELECT * WHERE { ?a <http://isA> ?b }";
+        final Document actual = docConverter.makeMetadataDocument("pcjTest", sparql);
+        final Document expected = new Document()
+                .append(MongoPcjDocuments.CARDINALITY_FIELD, 0)
+                .append(MongoPcjDocuments.PCJ_METADATA_ID, "pcjTest_METADATA")
+                .append(MongoPcjDocuments.SPARQL_FIELD, sparql)
+                .append(MongoPcjDocuments.VAR_ORDER_FIELD, Sets.newHashSet(new VariableOrder("a", "b"), new VariableOrder("b", "a")));
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void metadataExists() throws Exception {
+        final List<VariableOrder> varOrders = Lists.newArrayList(new VariableOrder("b", "a"), new VariableOrder("a", "b"));
+        final MongoPcjDocuments docConverter = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+        final String sparql = "SELECT * WHERE { ?a <http://isA> ?b }";
+        docConverter.createPcj("pcjTest", sparql);
+
+        PcjMetadata actual = docConverter.getPcjMetadata("pcjTest");
+        PcjMetadata expected = new PcjMetadata(sparql, 0, varOrders);
+        assertEquals(expected, actual);
+
+        // Setup the binding set that will be converted.
+        final MapBindingSet originalBindingSet1 = new MapBindingSet();
+        originalBindingSet1.addBinding("x", new URIImpl("http://a"));
+        originalBindingSet1.addBinding("y", new URIImpl("http://b"));
+        originalBindingSet1.addBinding("z", new URIImpl("http://c"));
+        final VisibilityBindingSet results1 = new VisibilityBindingSet(originalBindingSet1, "A&B&C");
+
+        // Setup the binding set that will be converted.
+        final MapBindingSet originalBindingSet2 = new MapBindingSet();
+        originalBindingSet2.addBinding("x", new URIImpl("http://1"));
+        originalBindingSet2.addBinding("y", new URIImpl("http://2"));
+        originalBindingSet2.addBinding("z", new URIImpl("http://3"));
+        final VisibilityBindingSet results2 = new VisibilityBindingSet(originalBindingSet2, "A&B&C");
+
+        final List<VisibilityBindingSet> bindingSets = new ArrayList<>();
+        bindingSets.add(results1);
+        bindingSets.add(results2);
+
+        docConverter.addResults("pcjTest", bindingSets);
+        actual = docConverter.getPcjMetadata("pcjTest");
+        expected = new PcjMetadata(sparql, 2, varOrders);
+        assertEquals(expected, actual);
+
+        docConverter.purgePcjs("pcjTest");
+        actual = docConverter.getPcjMetadata("pcjTest");
+        expected = new PcjMetadata(sparql, 0, varOrders);
+        assertEquals(expected, actual);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjStorageIT.java
----------------------------------------------------------------------
diff --git a/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjStorageIT.java b/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjStorageIT.java
new file mode 100644
index 0000000..6747558
--- /dev/null
+++ b/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/MongoPcjStorageIT.java
@@ -0,0 +1,348 @@
+/**
+ * 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.
+ */
+package org.apache.rya.indexing.pcj.storage.mongo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.rya.api.instance.RyaDetails;
+import org.apache.rya.api.instance.RyaDetails.EntityCentricIndexDetails;
+import org.apache.rya.api.instance.RyaDetails.FreeTextIndexDetails;
+import org.apache.rya.api.instance.RyaDetails.JoinSelectivityDetails;
+import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails;
+import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.PCJDetails;
+import org.apache.rya.api.instance.RyaDetails.ProspectorDetails;
+import org.apache.rya.api.instance.RyaDetails.TemporalIndexDetails;
+import org.apache.rya.api.model.VisibilityBindingSet;
+import org.apache.rya.api.utils.CloseableIterator;
+import org.apache.rya.indexing.pcj.storage.PcjMetadata;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage;
+import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjStorage;
+import org.apache.rya.indexing.pcj.storage.accumulo.ShiftVarOrderFactory;
+import org.apache.rya.indexing.pcj.storage.accumulo.VariableOrder;
+import org.apache.rya.mongodb.MongoITBase;
+import org.apache.rya.mongodb.instance.MongoRyaInstanceDetailsRepository;
+import org.junit.Test;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.impl.MapBindingSet;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Integration tests the methods of {@link AccumuloPcjStorage}.
+ * </p>
+ * These tests ensures that the PCJ tables are maintained and that these operations
+ * also update the Rya instance's details.
+ */
+public class MongoPcjStorageIT extends MongoITBase {
+
+    @Test
+    public void createPCJ() throws Exception {
+        // Setup the PCJ storage that will be tested against.
+        try(final PrecomputedJoinStorage pcjStorage =  new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            // Create a PCJ.
+            final MongoRyaInstanceDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(getMongoClient(), conf.getRyaInstanceName());
+            detailsRepo.initialize(
+                    RyaDetails.builder()
+                    .setRyaInstanceName(conf.getRyaInstanceName())
+                    .setRyaVersion("test")
+                    .setEntityCentricIndexDetails(new EntityCentricIndexDetails(false))
+                    .setTemporalIndexDetails(new TemporalIndexDetails(false))
+                    .setFreeTextDetails(new FreeTextIndexDetails(false))
+                    .setProspectorDetails(new ProspectorDetails(Optional.absent()))
+                    .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.absent()))
+                    .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(true))
+                    .build()
+                    );
+            final String pcjId = pcjStorage.createPcj("SELECT * WHERE { ?a <http://isA> ?b } ");
+
+            // Ensure the Rya details have been updated to include the PCJ's ID.
+            final ImmutableMap<String, PCJDetails> detailsMap = detailsRepo.getRyaInstanceDetails()
+                    .getPCJIndexDetails()
+                    .getPCJDetails();
+
+            final PCJDetails expectedDetails = PCJDetails.builder()
+                    .setId( pcjId )
+                    .build();
+
+            assertEquals(expectedDetails, detailsMap.get(pcjId));
+        }
+    }
+
+
+    @Test
+    public void dropPCJ() throws Exception {
+        try(final PrecomputedJoinStorage pcjStorage =  new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            final MongoRyaInstanceDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(getMongoClient(), conf.getRyaInstanceName());
+            detailsRepo.initialize(
+                    RyaDetails.builder()
+                    .setRyaInstanceName(conf.getRyaInstanceName())
+                    .setRyaVersion("test")
+                    .setEntityCentricIndexDetails(new EntityCentricIndexDetails(false))
+                    .setTemporalIndexDetails(new TemporalIndexDetails(false))
+                    .setFreeTextDetails(new FreeTextIndexDetails(false))
+                    .setProspectorDetails(new ProspectorDetails(Optional.absent()))
+                    .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.absent()))
+                    .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(true))
+                    .build()
+                    );
+            // Create a PCJ.
+            final String pcjId = pcjStorage.createPcj("SELECT * WHERE { ?a <http://isA> ?b } ");
+
+            // Delete the PCJ that was just created.
+            pcjStorage.dropPcj(pcjId);
+
+            // Ensure the Rya details have been updated to no longer include the PCJ's ID.
+
+            final ImmutableMap<String, PCJDetails> detailsMap = detailsRepo.getRyaInstanceDetails()
+                    .getPCJIndexDetails()
+                    .getPCJDetails();
+
+            assertFalse( detailsMap.containsKey(pcjId) );
+        }
+    }
+
+    @Test
+    public void listPcjs() throws Exception {
+        try(final PrecomputedJoinStorage pcjStorage =  new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            final MongoRyaInstanceDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(getMongoClient(), conf.getRyaInstanceName());
+            detailsRepo.initialize(
+                    RyaDetails.builder()
+                    .setRyaInstanceName(conf.getRyaInstanceName())
+                    .setRyaVersion("test")
+                    .setEntityCentricIndexDetails(new EntityCentricIndexDetails(false))
+                    .setTemporalIndexDetails(new TemporalIndexDetails(false))
+                    .setFreeTextDetails(new FreeTextIndexDetails(false))
+                    .setProspectorDetails(new ProspectorDetails(Optional.absent()))
+                    .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.absent()))
+                    .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(true))
+                    .build()
+                    );
+            // Create a few PCJs and hold onto their IDs.
+            final List<String> expectedIds = new ArrayList<>();
+
+            String pcjId = pcjStorage.createPcj("SELECT * WHERE { ?a <http://isA> ?b } ");
+            expectedIds.add( pcjId );
+
+            pcjId = pcjStorage.createPcj("SELECT * WHERE { ?a <http://isA> ?b } ");
+            expectedIds.add( pcjId );
+
+            pcjId = pcjStorage.createPcj("SELECT * WHERE { ?a <http://isA> ?b } ");
+            expectedIds.add( pcjId );
+
+            // Fetch the PCJ names
+            final List<String> pcjIds = pcjStorage.listPcjs();
+
+            // Ensure the expected IDs match the fetched IDs.
+            Collections.sort(expectedIds);
+            Collections.sort(pcjIds);
+            assertEquals(expectedIds, pcjIds);
+        }
+    }
+
+    @Test
+    public void getPcjMetadata() throws Exception {
+        try(final PrecomputedJoinStorage pcjStorage =  new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            final MongoRyaInstanceDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(getMongoClient(), conf.getRyaInstanceName());
+            detailsRepo.initialize(
+                    RyaDetails.builder()
+                    .setRyaInstanceName(conf.getRyaInstanceName())
+                    .setRyaVersion("test")
+                    .setEntityCentricIndexDetails(new EntityCentricIndexDetails(false))
+                    .setTemporalIndexDetails(new TemporalIndexDetails(false))
+                    .setFreeTextDetails(new FreeTextIndexDetails(false))
+                    .setProspectorDetails(new ProspectorDetails(Optional.absent()))
+                    .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.absent()))
+                    .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(true))
+                    .build()
+                    );
+            // Create a PCJ.
+            final String sparql = "SELECT * WHERE { ?a <http://isA> ?b }";
+            final String pcjId = pcjStorage.createPcj(sparql);
+
+            // Fetch the PCJ's metadata.
+            final PcjMetadata metadata = pcjStorage.getPcjMetadata(pcjId);
+
+            // Ensure it has the expected values.
+            final Set<VariableOrder> varOrders = new ShiftVarOrderFactory().makeVarOrders(sparql);
+            final PcjMetadata expectedMetadata = new PcjMetadata(sparql, 0L, varOrders);
+            assertEquals(expectedMetadata, metadata);
+        }
+    }
+
+    @Test
+    public void addResults() throws Exception {
+        try(final PrecomputedJoinStorage pcjStorage =  new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            final MongoRyaInstanceDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(getMongoClient(), conf.getRyaInstanceName());
+            detailsRepo.initialize(
+                    RyaDetails.builder()
+                    .setRyaInstanceName(conf.getRyaInstanceName())
+                    .setRyaVersion("test")
+                    .setEntityCentricIndexDetails(new EntityCentricIndexDetails(false))
+                    .setTemporalIndexDetails(new TemporalIndexDetails(false))
+                    .setFreeTextDetails(new FreeTextIndexDetails(false))
+                    .setProspectorDetails(new ProspectorDetails(Optional.absent()))
+                    .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.absent()))
+                    .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(true))
+                    .build()
+                    );
+            // Create a PCJ.
+            final String sparql = "SELECT * WHERE { ?a <http://isA> ?b }";
+            final String pcjId = pcjStorage.createPcj(sparql);
+
+            // Add some binding sets to it.
+            final Set<VisibilityBindingSet> results = new HashSet<>();
+
+            final MapBindingSet aliceBS = new MapBindingSet();
+            aliceBS.addBinding("a", new URIImpl("http://Alice"));
+            aliceBS.addBinding("b", new URIImpl("http://Person"));
+            results.add( new VisibilityBindingSet(aliceBS, "") );
+
+            final MapBindingSet charlieBS = new MapBindingSet();
+            charlieBS.addBinding("a", new URIImpl("http://Charlie"));
+            charlieBS.addBinding("b", new URIImpl("http://Comedian"));
+            results.add( new VisibilityBindingSet(charlieBS, "") );
+
+            pcjStorage.addResults(pcjId, results);
+
+            // Make sure the PCJ metadata was updated.
+            final PcjMetadata metadata = pcjStorage.getPcjMetadata(pcjId);
+
+            final Set<VariableOrder> varOrders = new ShiftVarOrderFactory().makeVarOrders(sparql);
+            final PcjMetadata expectedMetadata = new PcjMetadata(sparql, 2L, varOrders);
+            assertEquals(expectedMetadata, metadata);
+        }
+    }
+
+    @Test
+    public void listResults() throws Exception {
+        try(final PrecomputedJoinStorage pcjStorage =  new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            final MongoRyaInstanceDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(getMongoClient(), conf.getRyaInstanceName());
+            detailsRepo.initialize(
+                    RyaDetails.builder()
+                    .setRyaInstanceName(conf.getRyaInstanceName())
+                    .setRyaVersion("test")
+                    .setEntityCentricIndexDetails(new EntityCentricIndexDetails(false))
+                    .setTemporalIndexDetails(new TemporalIndexDetails(false))
+                    .setFreeTextDetails(new FreeTextIndexDetails(false))
+                    .setProspectorDetails(new ProspectorDetails(Optional.absent()))
+                    .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.absent()))
+                    .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(true))
+                    .build()
+                    );
+            // Create a PCJ.
+            final String sparql = "SELECT * WHERE { ?a <http://isA> ?b }";
+            final String pcjId = pcjStorage.createPcj(sparql);
+
+            // Add some binding sets to it.
+            final Set<VisibilityBindingSet> visiSets = new HashSet<>();
+            final Set<BindingSet> expectedResults = new HashSet<>();
+
+            final MapBindingSet aliceBS = new MapBindingSet();
+            aliceBS.addBinding("a", new URIImpl("http://Alice"));
+            aliceBS.addBinding("b", new URIImpl("http://Person"));
+            visiSets.add( new VisibilityBindingSet(aliceBS, "") );
+            expectedResults.add(aliceBS);
+
+            final MapBindingSet charlieBS = new MapBindingSet();
+            charlieBS.addBinding("a", new URIImpl("http://Charlie"));
+            charlieBS.addBinding("b", new URIImpl("http://Comedian"));
+            visiSets.add( new VisibilityBindingSet(charlieBS, "") );
+            expectedResults.add(charlieBS);
+
+            pcjStorage.addResults(pcjId, visiSets);
+
+            // List the results that were stored.
+            final Set<BindingSet> results = new HashSet<>();
+            try(CloseableIterator<BindingSet> resultsIt = pcjStorage.listResults(pcjId)) {
+                while(resultsIt.hasNext()) {
+                    results.add( resultsIt.next() );
+                }
+            }
+
+            assertEquals(expectedResults, results);
+        }
+    }
+
+    @Test
+    public void purge() throws Exception {
+        try(final PrecomputedJoinStorage pcjStorage =  new MongoPcjStorage(getMongoClient(), conf.getRyaInstanceName())) {
+            final MongoRyaInstanceDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(getMongoClient(), conf.getRyaInstanceName());
+            detailsRepo.initialize(
+                    RyaDetails.builder()
+                    .setRyaInstanceName(conf.getRyaInstanceName())
+                    .setRyaVersion("test")
+                    .setEntityCentricIndexDetails(new EntityCentricIndexDetails(false))
+                    .setTemporalIndexDetails(new TemporalIndexDetails(false))
+                    .setFreeTextDetails(new FreeTextIndexDetails(false))
+                    .setProspectorDetails(new ProspectorDetails(Optional.absent()))
+                    .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.absent()))
+                    .setPCJIndexDetails(PCJIndexDetails.builder().setEnabled(true))
+                    .build()
+                    );
+            // Create a PCJ.
+            final String sparql = "SELECT * WHERE { ?a <http://isA> ?b }";
+            final String pcjId = pcjStorage.createPcj(sparql);
+
+            // Add some binding sets to it.
+            final Set<VisibilityBindingSet> expectedResults = new HashSet<>();
+
+            final MapBindingSet aliceBS = new MapBindingSet();
+            aliceBS.addBinding("a", new URIImpl("http://Alice"));
+            aliceBS.addBinding("b", new URIImpl("http://Person"));
+            expectedResults.add( new VisibilityBindingSet(aliceBS, "") );
+
+            final MapBindingSet charlieBS = new MapBindingSet();
+            charlieBS.addBinding("a", new URIImpl("http://Charlie"));
+            charlieBS.addBinding("b", new URIImpl("http://Comedian"));
+            expectedResults.add( new VisibilityBindingSet(charlieBS, "") );
+
+            pcjStorage.addResults(pcjId, expectedResults);
+
+            // Purge the PCJ.
+            pcjStorage.purge(pcjId);
+
+            // List the results that were stored.
+            final Set<BindingSet> results = new HashSet<>();
+            try(CloseableIterator<BindingSet> resultsIt = pcjStorage.listResults(pcjId)) {
+                while(resultsIt.hasNext()) {
+                    results.add( resultsIt.next() );
+                }
+            }
+
+            assertTrue( results.isEmpty() );
+
+            // Make sure the PCJ metadata was updated.
+            final PcjMetadata metadata = pcjStorage.getPcjMetadata(pcjId);
+
+            final Set<VariableOrder> varOrders = new ShiftVarOrderFactory().makeVarOrders(sparql);
+            final PcjMetadata expectedMetadata = new PcjMetadata(sparql, 0L, varOrders);
+            assertEquals(expectedMetadata, metadata);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/PcjDocumentsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/PcjDocumentsIntegrationTest.java b/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/PcjDocumentsIntegrationTest.java
new file mode 100644
index 0000000..0c71c9f
--- /dev/null
+++ b/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/PcjDocumentsIntegrationTest.java
@@ -0,0 +1,460 @@
+/**
+ * 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.
+ */
+package org.apache.rya.indexing.pcj.storage.mongo;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.minicluster.MiniAccumuloCluster;
+import org.apache.rya.api.model.VisibilityBindingSet;
+import org.apache.rya.api.utils.CloseableIterator;
+import org.apache.rya.indexing.pcj.storage.PcjException;
+import org.apache.rya.indexing.pcj.storage.PcjMetadata;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException;
+import org.apache.rya.indexing.pcj.storage.accumulo.BindingSetConverter.BindingSetConversionException;
+import org.apache.rya.indexing.pcj.storage.accumulo.PcjTableNameFactory;
+import org.apache.rya.indexing.pcj.storage.accumulo.PcjTables;
+import org.apache.rya.indexing.pcj.storage.accumulo.VariableOrder;
+import org.apache.rya.mongodb.MongoDBRdfConfiguration;
+import org.apache.rya.mongodb.MongoDBRyaDAO;
+import org.apache.rya.mongodb.MongoITBase;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
+import org.apache.rya.rdftriplestore.RdfCloudTripleStore;
+import org.apache.rya.rdftriplestore.RyaSailRepository;
+import org.junit.Test;
+import org.openrdf.model.Statement;
+import org.openrdf.model.impl.LiteralImpl;
+import org.openrdf.model.impl.NumericLiteralImpl;
+import org.openrdf.model.impl.StatementImpl;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.model.vocabulary.XMLSchema;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.impl.MapBindingSet;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.sail.SailRepositoryConnection;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+
+/**
+ * Performs integration test using {@link MiniAccumuloCluster} to ensure the
+ * functions of {@link PcjTables} work within a cluster setting.
+ */
+public class PcjDocumentsIntegrationTest extends MongoITBase {
+    @Override
+    protected void updateConfiguration(final MongoDBRdfConfiguration conf) {
+        conf.setDisplayQueryPlan(true);
+    }
+
+    /**
+     * Ensure that when a new PCJ table is created, it is initialized with the
+     * correct metadata values.
+     * <p>
+     * The method being tested is {@link PcjTables#createPcjTable(Connector, String, Set, String)}
+     */
+    @Test
+    public void createPcjTable() throws PcjException, AccumuloException, AccumuloSecurityException {
+        final String sparql =
+                "SELECT ?name ?age " +
+                        "{" +
+                        "FILTER(?age < 30) ." +
+                        "?name <http://hasAge> ?age." +
+                        "?name <http://playsSport> \"Soccer\" " +
+                        "}";
+
+        final String pcjTableName = "testPcj";
+        final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+        pcjs.createPcj(pcjTableName, sparql);
+
+        // Fetch the PcjMetadata and ensure it has the correct values.
+        final PcjMetadata pcjMetadata = pcjs.getPcjMetadata(pcjTableName);
+
+        // Ensure the metadata matches the expected value.
+        final PcjMetadata expected = new PcjMetadata(sparql, 0L, Sets.newHashSet(new VariableOrder("name", "age"), new VariableOrder("age", "name")));
+        assertEquals(expected, pcjMetadata);
+    }
+
+    /**
+     * Ensure when results have been written to the PCJ table that they are in Accumulo.
+     * <p>
+     * The method being tested is {@link PcjTables#addResults(Connector, String, java.util.Collection)}
+     */
+    @Test
+    public void addResults() throws Exception {
+        final String sparql =
+                "SELECT ?name ?age " +
+                        "{" +
+                        "FILTER(?age < 30) ." +
+                        "?name <http://hasAge> ?age." +
+                        "?name <http://playsSport> \"Soccer\" " +
+                        "}";
+
+        final String pcjTableName = "testPcj";
+        final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+        pcjs.createPcj(pcjTableName, sparql);
+
+        // Add a few results to the PCJ table.
+        final MapBindingSet alice = new MapBindingSet();
+        alice.addBinding("name", new URIImpl("http://Alice"));
+        alice.addBinding("age", new NumericLiteralImpl(14, XMLSchema.INTEGER));
+
+        final MapBindingSet bob = new MapBindingSet();
+        bob.addBinding("name", new URIImpl("http://Bob"));
+        bob.addBinding("age", new NumericLiteralImpl(16, XMLSchema.INTEGER));
+
+        final MapBindingSet charlie = new MapBindingSet();
+        charlie.addBinding("name", new URIImpl("http://Charlie"));
+        charlie.addBinding("age", new NumericLiteralImpl(12, XMLSchema.INTEGER));
+
+        final Set<BindingSet> expected = Sets.<BindingSet>newHashSet(alice, bob, charlie);
+        pcjs.addResults(pcjTableName, Sets.<VisibilityBindingSet>newHashSet(
+                new VisibilityBindingSet(alice),
+                new VisibilityBindingSet(bob),
+                new VisibilityBindingSet(charlie)));
+
+        // Make sure the cardinality was updated.
+        final PcjMetadata metadata = pcjs.getPcjMetadata(pcjTableName);
+        assertEquals(3, metadata.getCardinality());
+
+        // Scan Accumulo for the stored results.
+        final Collection<BindingSet> fetchedResults = loadPcjResults(pcjTableName);
+        assertEquals(expected, fetchedResults);
+    }
+
+    @Test
+    public void listResults() throws Exception {
+        final String sparql =
+                "SELECT ?name ?age " +
+                        "{" +
+                        "FILTER(?age < 30) ." +
+                        "?name <http://hasAge> ?age." +
+                        "?name <http://playsSport> \"Soccer\" " +
+                        "}";
+
+        final String pcjTableName = "testPcj";
+        final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+        pcjs.createPcj(pcjTableName, sparql);
+
+        // Add a few results to the PCJ table.
+        final MapBindingSet alice = new MapBindingSet();
+        alice.addBinding("name", new URIImpl("http://Alice"));
+        alice.addBinding("age", new NumericLiteralImpl(14, XMLSchema.INTEGER));
+
+        final MapBindingSet bob = new MapBindingSet();
+        bob.addBinding("name", new URIImpl("http://Bob"));
+        bob.addBinding("age", new NumericLiteralImpl(16, XMLSchema.INTEGER));
+
+        final MapBindingSet charlie = new MapBindingSet();
+        charlie.addBinding("name", new URIImpl("http://Charlie"));
+        charlie.addBinding("age", new NumericLiteralImpl(12, XMLSchema.INTEGER));
+
+        pcjs.addResults(pcjTableName, Sets.<VisibilityBindingSet>newHashSet(
+                new VisibilityBindingSet(alice),
+                new VisibilityBindingSet(bob),
+                new VisibilityBindingSet(charlie)));
+
+        // Fetch the Binding Sets that have been stored in the PCJ table.
+        final Set<BindingSet> results = new HashSet<>();
+
+        final CloseableIterator<BindingSet> resultsIt = pcjs.listResults(pcjTableName);
+        try {
+            while(resultsIt.hasNext()) {
+                results.add( resultsIt.next() );
+            }
+        } finally {
+            resultsIt.close();
+        }
+
+        // Verify the fetched results match the expected ones.
+        final Set<BindingSet> expected = Sets.<BindingSet>newHashSet(alice, bob, charlie);
+        assertEquals(expected, results);
+    }
+
+    /**
+     * Ensure when results are already stored in Rya, that we are able to populate
+     * the PCJ table for a new SPARQL query using those results.
+     * <p>
+     * The method being tested is: {@link PcjTables#populatePcj(Connector, String, RepositoryConnection, String)}
+     */
+    @Test
+    public void populatePcj() throws Exception {
+        final MongoDBRyaDAO dao = new MongoDBRyaDAO();
+        dao.setConf(new StatefulMongoDBRdfConfiguration(conf, getMongoClient()));
+        dao.init();
+        final RdfCloudTripleStore ryaStore = new RdfCloudTripleStore();
+        ryaStore.setRyaDAO(dao);
+        ryaStore.initialize();
+        final SailRepositoryConnection ryaConn = new RyaSailRepository(ryaStore).getConnection();
+        ryaConn.begin();
+
+        try {
+            // Load some Triples into Rya.
+            final Set<Statement> triples = new HashSet<>();
+            triples.add( new StatementImpl(new URIImpl("http://Alice"), new URIImpl("http://hasAge"), new NumericLiteralImpl(14, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Alice"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Bob"), new URIImpl("http://hasAge"), new NumericLiteralImpl(16, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Bob"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Charlie"), new URIImpl("http://hasAge"), new NumericLiteralImpl(12, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Charlie"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Eve"), new URIImpl("http://hasAge"), new NumericLiteralImpl(43, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Eve"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+
+            for(final Statement triple : triples) {
+                ryaConn.add(triple);
+            }
+
+            // Create a PCJ table that will include those triples in its results.
+            final String sparql =
+                    "SELECT ?name ?age " +
+                            "{" +
+                            "FILTER(?age < 30) ." +
+                            "?name <http://hasAge> ?age." +
+                            "?name <http://playsSport> \"Soccer\" " +
+                            "}";
+
+            final String pcjTableName = "testPcj";
+            final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+            pcjs.createPcj(pcjTableName, sparql);
+
+            // Populate the PCJ table using a Rya connection.
+            pcjs.populatePcj(pcjTableName, ryaConn);
+
+            final Collection<BindingSet> fetchedResults = loadPcjResults(pcjTableName);
+
+            // Make sure the cardinality was updated.
+            final PcjMetadata metadata = pcjs.getPcjMetadata(pcjTableName);
+            assertEquals(3, metadata.getCardinality());
+
+            // Ensure the expected results match those that were stored.
+            final MapBindingSet alice = new MapBindingSet();
+            alice.addBinding("name", new URIImpl("http://Alice"));
+            alice.addBinding("age", new NumericLiteralImpl(14, XMLSchema.INTEGER));
+
+            final MapBindingSet bob = new MapBindingSet();
+            bob.addBinding("name", new URIImpl("http://Bob"));
+            bob.addBinding("age", new NumericLiteralImpl(16, XMLSchema.INTEGER));
+
+            final MapBindingSet charlie = new MapBindingSet();
+            charlie.addBinding("name", new URIImpl("http://Charlie"));
+            charlie.addBinding("age", new NumericLiteralImpl(12, XMLSchema.INTEGER));
+
+            final Set<BindingSet> expected = Sets.<BindingSet>newHashSet(alice, bob, charlie);
+
+            assertEquals(expected, fetchedResults);
+        } finally {
+            ryaConn.close();
+            ryaStore.shutDown();
+        }
+    }
+
+    /**
+     * Ensure the method that creates a new PCJ table, scans Rya for matches, and
+     * stores them in the PCJ table works.
+     * <p>
+     * The method being tested is: {@link PcjTables#createAndPopulatePcj(RepositoryConnection, Connector, String, String, String[], Optional)}
+     */
+    @Test
+    public void createAndPopulatePcj() throws Exception {
+        final MongoDBRyaDAO dao = new MongoDBRyaDAO();
+        dao.setConf(new StatefulMongoDBRdfConfiguration(conf, getMongoClient()));
+        dao.init();
+        final RdfCloudTripleStore ryaStore = new RdfCloudTripleStore();
+        ryaStore.setRyaDAO(dao);
+        ryaStore.initialize();
+        final SailRepositoryConnection ryaConn = new RyaSailRepository(ryaStore).getConnection();
+        ryaConn.begin();
+
+        try {
+            // Load some Triples into Rya.
+            final Set<Statement> triples = new HashSet<>();
+            triples.add( new StatementImpl(new URIImpl("http://Alice"), new URIImpl("http://hasAge"), new NumericLiteralImpl(14, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Alice"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Bob"), new URIImpl("http://hasAge"), new NumericLiteralImpl(16, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Bob"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Charlie"), new URIImpl("http://hasAge"), new NumericLiteralImpl(12, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Charlie"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Eve"), new URIImpl("http://hasAge"), new NumericLiteralImpl(43, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Eve"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+
+            for(final Statement triple : triples) {
+                ryaConn.add(triple);
+            }
+
+            // Create a PCJ table that will include those triples in its results.
+            final String sparql =
+                    "SELECT ?name ?age " +
+                            "{" +
+                            "FILTER(?age < 30) ." +
+                            "?name <http://hasAge> ?age." +
+                            "?name <http://playsSport> \"Soccer\" " +
+                            "}";
+
+            final String pcjTableName = "testPcj";
+
+            // Create and populate the PCJ table.
+            final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+            pcjs.createAndPopulatePcj(ryaConn, pcjTableName, sparql);
+
+            // Make sure the cardinality was updated.
+            final PcjMetadata metadata = pcjs.getPcjMetadata(pcjTableName);
+            assertEquals(3, metadata.getCardinality());
+
+            // Scan Accumulo for the stored results.
+            final Collection<BindingSet> fetchedResults = loadPcjResults(pcjTableName);
+
+            // Ensure the expected results match those that were stored.
+            final MapBindingSet alice = new MapBindingSet();
+            alice.addBinding("name", new URIImpl("http://Alice"));
+            alice.addBinding("age", new NumericLiteralImpl(14, XMLSchema.INTEGER));
+
+            final MapBindingSet bob = new MapBindingSet();
+            bob.addBinding("name", new URIImpl("http://Bob"));
+            bob.addBinding("age", new NumericLiteralImpl(16, XMLSchema.INTEGER));
+
+            final MapBindingSet charlie = new MapBindingSet();
+            charlie.addBinding("name", new URIImpl("http://Charlie"));
+            charlie.addBinding("age", new NumericLiteralImpl(12, XMLSchema.INTEGER));
+
+            final Set<BindingSet> expected = Sets.<BindingSet>newHashSet(alice, bob, charlie);
+
+            assertEquals(expected, fetchedResults);
+        } finally {
+            ryaConn.close();
+            ryaStore.shutDown();
+        }
+    }
+
+    @Test
+    public void listPcjs() throws Exception {
+        // Set up the table names that will be used.
+        final String instance1 = "instance1_";
+        final String instance2 = "instance2_";
+
+        final String instance1_table1 = new PcjTableNameFactory().makeTableName(instance1, "table1");
+        final String instance1_table2 = new PcjTableNameFactory().makeTableName(instance1, "table2");
+        final String instance1_table3 = new PcjTableNameFactory().makeTableName(instance1, "table3");
+
+        final String instance2_table1 = new PcjTableNameFactory().makeTableName(instance2, "table1");
+
+        // Create the PCJ Tables that are in instance 1 and instance 2.
+        final String sparql = "SELECT ?x WHERE { ?x <http://isA> <http://Food> }";
+
+        final MongoPcjDocuments pcjs1 = new MongoPcjDocuments(getMongoClient(), instance1);
+        final MongoPcjDocuments pcjs2 = new MongoPcjDocuments(getMongoClient(), instance2);
+        pcjs1.createPcj(instance1_table1, sparql);
+        pcjs1.createPcj(instance1_table2, sparql);
+        pcjs1.createPcj(instance1_table3, sparql);
+
+        pcjs2.createPcj(instance2_table1, sparql);
+
+        // Ensure all of the names have been stored for instance 1 and 2.
+        final Set<String> expected1 = Sets.newHashSet(instance1_table1, instance1_table2, instance1_table3);
+        final Set<String> instance1Tables = Sets.newHashSet( pcjs1.listPcjDocuments() );
+        assertEquals(expected1, instance1Tables);
+
+        final Set<String> expected2 = Sets.newHashSet(instance2_table1);
+        final Set<String> instance2Tables = Sets.newHashSet( pcjs2.listPcjDocuments() );
+        assertEquals(expected2, instance2Tables);
+    }
+
+    @Test
+    public void purge() throws Exception {
+        final String sparql =
+                "SELECT ?name ?age " +
+                        "{" +
+                        "FILTER(?age < 30) ." +
+                        "?name <http://hasAge> ?age." +
+                        "?name <http://playsSport> \"Soccer\" " +
+                        "}";
+
+        final String pcjTableName = "testPcj";
+        final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+        pcjs.createPcj(pcjTableName, sparql);
+
+        // Add a few results to the PCJ table.
+        final MapBindingSet alice = new MapBindingSet();
+        alice.addBinding("name", new URIImpl("http://Alice"));
+        alice.addBinding("age", new NumericLiteralImpl(14, XMLSchema.INTEGER));
+
+        final MapBindingSet bob = new MapBindingSet();
+        bob.addBinding("name", new URIImpl("http://Bob"));
+        bob.addBinding("age", new NumericLiteralImpl(16, XMLSchema.INTEGER));
+
+        final MapBindingSet charlie = new MapBindingSet();
+        charlie.addBinding("name", new URIImpl("http://Charlie"));
+        charlie.addBinding("age", new NumericLiteralImpl(12, XMLSchema.INTEGER));
+
+        pcjs.addResults(pcjTableName, Sets.<VisibilityBindingSet>newHashSet(
+                new VisibilityBindingSet(alice),
+                new VisibilityBindingSet(bob),
+                new VisibilityBindingSet(charlie)));
+
+        // Make sure the cardinality was updated.
+        PcjMetadata metadata = pcjs.getPcjMetadata(pcjTableName);
+        assertEquals(3, metadata.getCardinality());
+
+        // Purge the data.
+        pcjs.purgePcjs(pcjTableName);
+
+        // Make sure the cardinality was updated to 0.
+        metadata = pcjs.getPcjMetadata(pcjTableName);
+        assertEquals(0, metadata.getCardinality());
+    }
+
+    @Test(expected=PCJStorageException.class)
+    public void dropPcj() throws Exception {
+        // Create a PCJ index.
+        final String pcjTableName = "testPcj";
+        final String sparql = "SELECT x WHERE ?x <http://isA> <http://Food>";
+
+        final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+        pcjs.createPcj(pcjTableName, sparql);
+
+        // Fetch its metadata to show that it has actually been created.
+        final PcjMetadata expectedMetadata = new PcjMetadata(sparql, 0L, new ArrayList<VariableOrder>());
+        PcjMetadata metadata = pcjs.getPcjMetadata(pcjTableName);
+        assertEquals(expectedMetadata, metadata);
+
+        // Drop it.
+        pcjs.dropPcj(pcjTableName);
+
+        // Show the metadata is no longer present.
+        metadata = pcjs.getPcjMetadata(pcjTableName);
+    }
+
+    private Collection<BindingSet> loadPcjResults(final String pcjTableName) throws PcjException, TableNotFoundException, BindingSetConversionException {
+
+        // Get the variable orders the data was written to.
+        final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+        final CloseableIterator<BindingSet> bindings = pcjs.listResults(pcjTableName);
+        final Set<BindingSet> bindingSets = new HashSet<>();
+        while(bindings.hasNext()) {
+            bindingSets.add(bindings.next());
+        }
+        return bindingSets;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/PcjDocumentsWithMockTest.java
----------------------------------------------------------------------
diff --git a/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/PcjDocumentsWithMockTest.java b/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/PcjDocumentsWithMockTest.java
new file mode 100644
index 0000000..a3ba747
--- /dev/null
+++ b/extras/rya.indexing.pcj/src/test/java/org/apache/rya/indexing/pcj/storage/mongo/PcjDocumentsWithMockTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.rya.indexing.pcj.storage.mongo;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.rya.indexing.pcj.storage.PcjMetadata;
+import org.apache.rya.indexing.pcj.storage.accumulo.PcjTableNameFactory;
+import org.apache.rya.mongodb.MongoDBRdfConfiguration;
+import org.apache.rya.mongodb.MongoDBRyaDAO;
+import org.apache.rya.mongodb.MongoITBase;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
+import org.apache.rya.rdftriplestore.RdfCloudTripleStore;
+import org.apache.rya.rdftriplestore.RyaSailRepository;
+import org.junit.Test;
+import org.openrdf.model.Statement;
+import org.openrdf.model.impl.LiteralImpl;
+import org.openrdf.model.impl.NumericLiteralImpl;
+import org.openrdf.model.impl.StatementImpl;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.model.vocabulary.XMLSchema;
+import org.openrdf.repository.sail.SailRepositoryConnection;
+
+public class PcjDocumentsWithMockTest extends MongoITBase {
+    @Override
+    protected void updateConfiguration(final MongoDBRdfConfiguration conf) {
+        conf.setDisplayQueryPlan(false);
+    }
+
+    @Test
+    public void populatePcj() throws Exception {
+        final RdfCloudTripleStore ryaStore = new RdfCloudTripleStore();
+        final MongoDBRyaDAO dao = new MongoDBRyaDAO();
+        dao.setConf(new StatefulMongoDBRdfConfiguration(conf, getMongoClient()));
+        dao.init();
+        ryaStore.setRyaDAO(dao);
+        ryaStore.initialize();
+        final SailRepositoryConnection ryaConn = new RyaSailRepository(ryaStore).getConnection();
+
+        try {
+            // Load some Triples into Rya.
+            final Set<Statement> triples = new HashSet<>();
+            triples.add( new StatementImpl(new URIImpl("http://Alice"), new URIImpl("http://hasAge"), new NumericLiteralImpl(14, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Alice"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Bob"), new URIImpl("http://hasAge"), new NumericLiteralImpl(16, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Bob"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Charlie"), new URIImpl("http://hasAge"), new NumericLiteralImpl(12, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Charlie"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+            triples.add( new StatementImpl(new URIImpl("http://Eve"), new URIImpl("http://hasAge"), new NumericLiteralImpl(43, XMLSchema.INTEGER)) );
+            triples.add( new StatementImpl(new URIImpl("http://Eve"), new URIImpl("http://playsSport"), new LiteralImpl("Soccer")) );
+
+            for(final Statement triple : triples) {
+                ryaConn.add(triple);
+            }
+
+            // Create a PCJ table that will include those triples in its results.
+            final String sparql =
+                    "SELECT ?name ?age " +
+                            "{" +
+                            "?name <http://hasAge> ?age." +
+                            "?name <http://playsSport> \"Soccer\" " +
+                            "}";
+
+            final String pcjTableName = new PcjTableNameFactory().makeTableName(conf.getRyaInstanceName(), "testPcj");
+            final MongoPcjDocuments pcjs = new MongoPcjDocuments(getMongoClient(), conf.getRyaInstanceName());
+            pcjs.createAndPopulatePcj(ryaConn, pcjTableName, sparql);
+
+            // Make sure the cardinality was updated.
+            final PcjMetadata metadata = pcjs.getPcjMetadata(pcjTableName);
+            assertEquals(4, metadata.getCardinality());
+        } finally {
+            ryaConn.close();
+            ryaStore.shutDown();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/CreateDeleteIT.java
----------------------------------------------------------------------
diff --git a/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/CreateDeleteIT.java b/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/CreateDeleteIT.java
index 7d6b241..ef5ab34 100644
--- a/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/CreateDeleteIT.java
+++ b/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/CreateDeleteIT.java
@@ -132,7 +132,7 @@ public class CreateDeleteIT extends RyaExportITBase {
         // Register the PCJ with Rya.
         final RyaClient ryaClient = AccumuloRyaClientFactory.build(createConnectionDetails(), getAccumuloConnector());
 
-        final String pcjId = ryaClient.getCreatePCJ().get().createPCJ(getRyaInstanceName(), sparql, Sets.newHashSet());
+        final String pcjId = ryaClient.getCreatePCJ().createPCJ(getRyaInstanceName(), sparql, Sets.newHashSet());
 
         // Write the data to Rya.
         final SailRepositoryConnection ryaConn = getRyaSailRepository().getConnection();

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/QueryIT.java
----------------------------------------------------------------------
diff --git a/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/QueryIT.java b/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/QueryIT.java
index 610f502..11415eb 100644
--- a/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/QueryIT.java
+++ b/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/integration/QueryIT.java
@@ -556,7 +556,7 @@ public class QueryIT extends RyaExportITBase {
         final Set<BindingSet> expectedResults = new HashSet<>();
 
         final long period = 1800000;
-        final long binId = (currentTime / period) * period;
+        final long binId = currentTime / period * period;
 
         MapBindingSet bs = new MapBindingSet();
         bs.addBinding("id", vf.createLiteral("id_1", XMLSchema.STRING));
@@ -657,7 +657,7 @@ public class QueryIT extends RyaExportITBase {
         final Set<BindingSet> expectedResults = new HashSet<>();
 
         final long period = 1800000;
-        final long binId = (currentTime / period) * period;
+        final long binId = currentTime / period * period;
 
         MapBindingSet bs = new MapBindingSet();
         bs.addBinding("total", vf.createLiteral("4", XMLSchema.INTEGER));
@@ -734,7 +734,7 @@ public class QueryIT extends RyaExportITBase {
         final Set<BindingSet> expectedResults = new HashSet<>();
 
         final long period = 1800000;
-        final long binId = (currentTime / period) * period;
+        final long binId = currentTime / period * period;
 
         MapBindingSet bs = new MapBindingSet();
         bs.addBinding("total", vf.createLiteral("2", XMLSchema.INTEGER));
@@ -854,7 +854,7 @@ public class QueryIT extends RyaExportITBase {
         final Set<BindingSet> expectedResults = new HashSet<>();
 
         final long period = 1800000;
-        final long binId = (currentTime / period) * period;
+        final long binId = currentTime / period * period;
 
         MapBindingSet bs = new MapBindingSet();
         bs.addBinding("total", vf.createLiteral("2", XMLSchema.INTEGER));
@@ -935,7 +935,7 @@ public class QueryIT extends RyaExportITBase {
         final Set<BindingSet> expectedResults = new HashSet<>();
 
         final long period = 1800000;
-        final long binId = (currentTime / period) * period;
+        final long binId = currentTime / period * period;
 
         MapBindingSet bs = new MapBindingSet();
         bs.addBinding("total", vf.createLiteral("2", XMLSchema.INTEGER));
@@ -996,7 +996,7 @@ public class QueryIT extends RyaExportITBase {
 
         switch (strategy) {
         case RYA:
-            ryaClient.getCreatePCJ().get().createPCJ(getRyaInstanceName(), sparql);
+            ryaClient.getCreatePCJ().createPCJ(getRyaInstanceName(), sparql);
             addStatementsAndWait(statements);
             // Fetch the value that is stored within the PCJ table.
             try (final PrecomputedJoinStorage pcjStorage = new AccumuloPcjStorage(accumuloConn, getRyaInstanceName())) {

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/visibility/PcjVisibilityIT.java
----------------------------------------------------------------------
diff --git a/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/visibility/PcjVisibilityIT.java b/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/visibility/PcjVisibilityIT.java
index 90ed01a..45be971 100644
--- a/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/visibility/PcjVisibilityIT.java
+++ b/extras/rya.pcj.fluo/pcj.fluo.integration/src/test/java/org/apache/rya/indexing/pcj/fluo/visibility/PcjVisibilityIT.java
@@ -104,7 +104,7 @@ public class PcjVisibilityIT extends RyaExportITBase {
 
         final RyaClient ryaClient = AccumuloRyaClientFactory.build(createConnectionDetails(), accumuloConn);
 
-        final String pcjId = ryaClient.getCreatePCJ().get().createPCJ(getRyaInstanceName(), sparql);
+        final String pcjId = ryaClient.getCreatePCJ().createPCJ(getRyaInstanceName(), sparql);
 
         // Grant the root user the "u" authorization.
         super.getAccumuloConnector().securityOperations().changeUserAuthorizations(getUsername(), new Authorizations("u"));

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.pcj.fluo/pcj.fluo.test.base/src/main/java/org/apache/rya/pcj/fluo/test/base/KafkaExportITBase.java
----------------------------------------------------------------------
diff --git a/extras/rya.pcj.fluo/pcj.fluo.test.base/src/main/java/org/apache/rya/pcj/fluo/test/base/KafkaExportITBase.java b/extras/rya.pcj.fluo/pcj.fluo.test.base/src/main/java/org/apache/rya/pcj/fluo/test/base/KafkaExportITBase.java
index 3b1b160..465e089 100644
--- a/extras/rya.pcj.fluo/pcj.fluo.test.base/src/main/java/org/apache/rya/pcj/fluo/test/base/KafkaExportITBase.java
+++ b/extras/rya.pcj.fluo/pcj.fluo.test.base/src/main/java/org/apache/rya/pcj/fluo/test/base/KafkaExportITBase.java
@@ -342,7 +342,7 @@ public class KafkaExportITBase extends AccumuloExportITBase {
         final RyaClient ryaClient = AccumuloRyaClientFactory.build(new AccumuloConnectionDetails(ACCUMULO_USER,
                 ACCUMULO_PASSWORD.toCharArray(), accInstance.getInstanceName(), accInstance.getZooKeepers()), accumuloConn);
 
-        final String pcjId = ryaClient.getCreatePCJ().get().createPCJ(RYA_INSTANCE_NAME, sparql, Sets.newHashSet(ExportStrategy.KAFKA));
+        final String pcjId = ryaClient.getCreatePCJ().createPCJ(RYA_INSTANCE_NAME, sparql, Sets.newHashSet(ExportStrategy.KAFKA));
 
         loadData(statements);
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/rya.pcj.fluo/rya.pcj.functions.geo/src/test/java/org/apache/rya/indexing/pcj/functions/geo/GeoFunctionsIT.java
----------------------------------------------------------------------
diff --git a/extras/rya.pcj.fluo/rya.pcj.functions.geo/src/test/java/org/apache/rya/indexing/pcj/functions/geo/GeoFunctionsIT.java b/extras/rya.pcj.fluo/rya.pcj.functions.geo/src/test/java/org/apache/rya/indexing/pcj/functions/geo/GeoFunctionsIT.java
index 894421a..f540a2e 100644
--- a/extras/rya.pcj.fluo/rya.pcj.functions.geo/src/test/java/org/apache/rya/indexing/pcj/functions/geo/GeoFunctionsIT.java
+++ b/extras/rya.pcj.fluo/rya.pcj.functions.geo/src/test/java/org/apache/rya/indexing/pcj/functions/geo/GeoFunctionsIT.java
@@ -342,7 +342,7 @@ public class GeoFunctionsIT extends RyaExportITBase {
                 accInstance.getInstanceName(),
                 accInstance.getZooKeepers()), accumuloConn);
 
-        ryaClient.getCreatePCJ().get().createPCJ(getRyaInstanceName(), sparql);
+        ryaClient.getCreatePCJ().createPCJ(getRyaInstanceName(), sparql);
 
         // Write the data to Rya.
         final SailRepositoryConnection ryaConn = super.getRyaSailRepository().getConnection();

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java b/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java
index ef33df1..17a2a23 100644
--- a/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java
+++ b/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java
@@ -166,11 +166,34 @@ public class RyaAdminCommands implements CommandMarker {
      */
     @CliAvailabilityIndicator({
         CREATE_PCJ_CMD,
-        DELETE_PCJ_CMD,
+        DELETE_PCJ_CMD})
+    public boolean arePCJCommandsAvailable() {
+        // The PCJ commands are only available if the Shell is connected to an instance of Rya
+        // that is new enough to use the RyaDetailsRepository and is configured to maintain PCJs.
+        final ShellState shellState = state.getShellState();
+        if(shellState.getConnectionState() == ConnectionState.CONNECTED_TO_INSTANCE) {
+            final GetInstanceDetails getInstanceDetails = shellState.getConnectedCommands().get().getGetInstanceDetails();
+            final String ryaInstanceName = state.getShellState().getRyaInstanceName().get();
+            try {
+                final Optional<RyaDetails> instanceDetails = getInstanceDetails.getDetails( ryaInstanceName );
+                if(instanceDetails.isPresent()) {
+                    return instanceDetails.get().getPCJIndexDetails().isEnabled();
+                }
+            } catch (final RyaClientException e) {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Enables commands that are available when the Shell is connected to a Rya Instance that supports PCJ Indexing.
+     */
+    @CliAvailabilityIndicator({
         CREATE_PERIODIC_PCJ_CMD,
         DELETE_PERIODIC_PCJ_CMD,
         LIST_INCREMENTAL_QUERIES})
-    public boolean arePCJCommandsAvailable() {
+    public boolean arePeriodicPCJCommandsAvailable() {
         // The PCJ commands are only available if the Shell is connected to an instance of Rya
         // that is new enough to use the RyaDetailsRepository and is configured to maintain PCJs.
         final ShellState shellState = state.getShellState();
@@ -267,8 +290,8 @@ public class RyaAdminCommands implements CommandMarker {
             final boolean enableFreeTextIndex,
 
             // TODO RYA-215
-//            @CliOption(key = {"enableGeospatialIndex"}, mandatory = false, help = "Use Geospatial Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
-//            final boolean enableGeospatialIndex,
+            //            @CliOption(key = {"enableGeospatialIndex"}, mandatory = false, help = "Use Geospatial Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
+            //            final boolean enableGeospatialIndex,
 
             @CliOption(key = {"enableTemporalIndex"}, mandatory = false, help = "Use Temporal Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
             final boolean enableTemporalIndex,
@@ -289,7 +312,7 @@ public class RyaAdminCommands implements CommandMarker {
                     .setEnableEntityCentricIndex(enableEntityCentricIndex)
                     .setEnableFreeTextIndex(enableFreeTextIndex)
                     // TODO RYA-215
-//                    .setEnableGeoIndex(enableGeospatialIndex)
+                    //                    .setEnableGeoIndex(enableGeospatialIndex)
                     .setEnableTemporalIndex(enableTemporalIndex)
                     .setEnablePcjIndex(enablePcjIndex)
                     .setFluoPcjAppName(fluoPcjAppName)
@@ -320,11 +343,14 @@ public class RyaAdminCommands implements CommandMarker {
             final boolean enableFreeTextIndex,
 
             // TODO RYA-215
-//            @CliOption(key = {"enableGeospatialIndex"}, mandatory = false, help = "Use Geospatial Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
-//            final boolean enableGeospatialIndex,
+            //            @CliOption(key = {"enableGeospatialIndex"}, mandatory = false, help = "Use Geospatial Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
+            //            final boolean enableGeospatialIndex,
 
             @CliOption(key = {"enableTemporalIndex"}, mandatory = false, help = "Use Temporal Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
-            final boolean enableTemporalIndex) {
+            final boolean enableTemporalIndex,
+
+            @CliOption(key = {"enablePcjIndex"}, mandatory = false, help = "Use Precomputed Join (PCJ) Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
+            final boolean enablePcjIndex) {
 
         // Fetch the commands that are connected to the store.
         final RyaClient commands = state.getShellState().getConnectedCommands().get();
@@ -333,8 +359,9 @@ public class RyaAdminCommands implements CommandMarker {
             final InstallConfiguration installConfig = InstallConfiguration.builder()
                     .setEnableFreeTextIndex(enableFreeTextIndex)
                     // TODO RYA-215
-//                    .setEnableGeoIndex(enableGeospatialIndex)
+                    //                    .setEnableGeoIndex(enableGeospatialIndex)
                     .setEnableTemporalIndex(enableTemporalIndex)
+                    .setEnablePcjIndex(enablePcjIndex)
                     .build();
 
             // Verify the configuration is what the user actually wants to do.
@@ -401,7 +428,7 @@ public class RyaAdminCommands implements CommandMarker {
             final Optional<String> sparql = sparqlPrompt.getSparql();
             if (sparql.isPresent()) {
                 // Execute the command.
-                final String pcjId = commands.getCreatePCJ().get().createPCJ(ryaInstance, sparql.get(), strategies);
+                final String pcjId = commands.getCreatePCJ().createPCJ(ryaInstance, sparql.get(), strategies);
                 // Return a message that indicates the ID of the newly created ID.
                 return String.format("The PCJ has been created. Its ID is '%s'.", pcjId);
             } else {
@@ -425,7 +452,7 @@ public class RyaAdminCommands implements CommandMarker {
 
         try {
             // Execute the command.
-            commands.getDeletePCJ().get().deletePCJ(ryaInstance, pcjId);
+            commands.getDeletePCJ().deletePCJ(ryaInstance, pcjId);
             return "The PCJ has been deleted.";
 
         } catch (final InstanceDoesNotExistException e) {

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/shell/src/main/java/org/apache/rya/shell/util/InstallPrompt.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/main/java/org/apache/rya/shell/util/InstallPrompt.java b/extras/shell/src/main/java/org/apache/rya/shell/util/InstallPrompt.java
index e92eadd..31480db 100644
--- a/extras/shell/src/main/java/org/apache/rya/shell/util/InstallPrompt.java
+++ b/extras/shell/src/main/java/org/apache/rya/shell/util/InstallPrompt.java
@@ -108,14 +108,14 @@ public interface InstallPrompt {
             checkState(storageType.isPresent(), "The shell must be connected to a storage to use the install prompt.");
 
             switch(sharedShellState.getShellState().getStorageType().get()) {
-                case ACCUMULO:
-                    return promptAccumuloVerified(instanceName, installConfig);
+            case ACCUMULO:
+                return promptAccumuloVerified(instanceName, installConfig);
 
-                case MONGO:
-                    return promptMongoVerified(instanceName, installConfig);
+            case MONGO:
+                return promptMongoVerified(instanceName, installConfig);
 
-                default:
-                    throw new IllegalStateException("Unsupported storage type: " + storageType.get());
+            default:
+                throw new IllegalStateException("Unsupported storage type: " + storageType.get());
             }
         }
 
@@ -143,9 +143,9 @@ public interface InstallPrompt {
             final boolean enableFreeTextIndexing = promptBoolean(prompt, Optional.of(true));
             builder.setEnableFreeTextIndex( enableFreeTextIndexing );
 
-// RYA-215            prompt = makeFieldPrompt("Use Geospatial Indexing", true);
-//            final boolean enableGeoIndexing = promptBoolean(prompt, Optional.of(true));
-//            builder.setEnableGeoIndex( enableGeoIndexing );
+            // RYA-215            prompt = makeFieldPrompt("Use Geospatial Indexing", true);
+            //            final boolean enableGeoIndexing = promptBoolean(prompt, Optional.of(true));
+            //            builder.setEnableGeoIndex( enableGeoIndexing );
 
             prompt = makeFieldPrompt("Use Temporal Indexing", true);
             final boolean useTemporalIndexing = promptBoolean(prompt, Optional.of(true));
@@ -188,7 +188,7 @@ public interface InstallPrompt {
             reader.println("   Use Shard Balancing: " + installConfig.isTableHashPrefixEnabled());
             reader.println("   Use Entity Centric Indexing: " + installConfig.isEntityCentrixIndexEnabled());
             reader.println("   Use Free Text Indexing: " + installConfig.isFreeTextIndexEnabled());
-// RYA-215            reader.println("   Use Geospatial Indexing: " + installConfig.isGeoIndexEnabled());
+            // RYA-215            reader.println("   Use Geospatial Indexing: " + installConfig.isGeoIndexEnabled());
             reader.println("   Use Temporal Indexing: " + installConfig.isTemporalIndexEnabled());
             reader.println("   Use Precomputed Join Indexing: " + installConfig.isPcjIndexEnabled());
             if(installConfig.isPcjIndexEnabled()) {
@@ -224,6 +224,10 @@ public interface InstallPrompt {
             final boolean useTemporalIndexing = promptBoolean(prompt, Optional.of(true));
             builder.setEnableTemporalIndex( useTemporalIndexing );
 
+            prompt = makeFieldPrompt("Use PCJ Indexing", true);
+            final boolean usePcjIndexing = promptBoolean(prompt, Optional.of(true));
+            builder.setEnablePcjIndex(usePcjIndexing);
+
             return builder.build();
         }
 
@@ -246,6 +250,7 @@ public interface InstallPrompt {
             reader.println("   Instance Name: " + instanceName);
             reader.println("   Use Free Text Indexing: " + installConfig.isFreeTextIndexEnabled());
             reader.println("   Use Temporal Indexing: " + installConfig.isTemporalIndexEnabled());
+            reader.println("   Use PCJ Indexing: " + installConfig.isPcjIndexEnabled());
             reader.println("");
 
             return promptBoolean("Continue with the install? (y/n) ", Optional.absent());

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/shell/src/main/java/org/apache/rya/shell/util/RyaDetailsFormatter.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/main/java/org/apache/rya/shell/util/RyaDetailsFormatter.java b/extras/shell/src/main/java/org/apache/rya/shell/util/RyaDetailsFormatter.java
index 3eacb54..2af1507 100644
--- a/extras/shell/src/main/java/org/apache/rya/shell/util/RyaDetailsFormatter.java
+++ b/extras/shell/src/main/java/org/apache/rya/shell/util/RyaDetailsFormatter.java
@@ -45,7 +45,7 @@ public class RyaDetailsFormatter {
      * @param details - The object to format. (not null)
      * @return A pretty render of the object.
      */
-    public String format(StorageType storageType, final RyaDetails details) {
+    public String format(final StorageType storageType, final RyaDetails details) {
         requireNonNull(details);
 
         final StringBuilder report = new StringBuilder();
@@ -72,41 +72,43 @@ public class RyaDetailsFormatter {
         report.append("  Temporal Index:\n");
         report.append("    Enabled: ").append( details.getTemporalIndexDetails().isEnabled() ).append("\n");
 
-        if(storageType == StorageType.ACCUMULO) {
-            report.append("  PCJ Index:\n");
-            final PCJIndexDetails pcjDetails = details.getPCJIndexDetails();
-            report.append("    Enabled: ").append( pcjDetails.isEnabled() ).append("\n");
-            if(pcjDetails.isEnabled()) {
-                if(pcjDetails.getFluoDetails().isPresent()) {
-                    final String fluoAppName = pcjDetails.getFluoDetails().get().getUpdateAppName();
-                    report.append("    Fluo App Name: ").append(fluoAppName).append("\n");
-                }
+        report.append("  PCJ Index:\n");
+        final PCJIndexDetails pcjDetails = details.getPCJIndexDetails();
+        report.append("    Enabled: ").append( pcjDetails.isEnabled() ).append("\n");
+        if(pcjDetails.isEnabled()) {
+            if(pcjDetails.getFluoDetails().isPresent()) {
+                final String fluoAppName = pcjDetails.getFluoDetails().get().getUpdateAppName();
+                report.append("    Fluo App Name: ").append(fluoAppName).append("\n");
+            }
 
-                final ImmutableMap<String, PCJDetails> pcjs = pcjDetails.getPCJDetails();
-                report.append("    PCJs:\n");
-                if(pcjs.isEmpty()) {
-                    report.append("      No PCJs have been added yet.\n");
-                } else {
-                    for(final PCJDetails pcj : pcjs.values()) {
-                        report.append("      ID: ").append(pcj.getId()).append("\n");
+            final ImmutableMap<String, PCJDetails> pcjs = pcjDetails.getPCJDetails();
+            report.append("    PCJs:\n");
+            if(pcjs.isEmpty()) {
+                report.append("      No PCJs have been added yet.\n");
+            } else {
+                for(final PCJDetails pcj : pcjs.values()) {
+                    report.append("      ID: ").append(pcj.getId()).append("\n");
 
-                        final String updateStrategy = format( pcj.getUpdateStrategy(), "None" );
-                        report.append("        Update Strategy: ").append(updateStrategy).append("\n");
+                    final String updateStrategy = format( pcj.getUpdateStrategy(), "None" );
+                    report.append("        Update Strategy: ").append(updateStrategy).append("\n");
 
-                        final String lastUpdateTime = format( pcj.getLastUpdateTime(), "unavailable");
-                        report.append("        Last Update Time: ").append(lastUpdateTime).append("\n");
-                    }
+                    final String lastUpdateTime = format( pcj.getLastUpdateTime(), "unavailable");
+                    report.append("        Last Update Time: ").append(lastUpdateTime).append("\n");
                 }
             }
 
-            report.append("Statistics:\n");
-            report.append("  Prospector:\n");
-            final String prospectorLastUpdateTime = format(details.getProspectorDetails().getLastUpdated(), "unavailable");
-            report.append("    Last Update Time: ").append( prospectorLastUpdateTime).append("\n");
-
-            report.append("  Join Selectivity:\n");
-            final String jsLastUpdateTime = format(details.getJoinSelectivityDetails().getLastUpdated(), "unavailable");
-            report.append("    Last Updated Time: ").append( jsLastUpdateTime ).append("\n");
+            if (storageType == StorageType.ACCUMULO) {
+                report.append("Statistics:\n");
+                report.append("  Prospector:\n");
+                final String prospectorLastUpdateTime = format(details.getProspectorDetails().getLastUpdated(),
+                        "unavailable");
+                report.append("    Last Update Time: ").append(prospectorLastUpdateTime).append("\n");
+
+                report.append("  Join Selectivity:\n");
+                final String jsLastUpdateTime = format(details.getJoinSelectivityDetails().getLastUpdated(),
+                        "unavailable");
+                report.append("    Last Updated Time: ").append(jsLastUpdateTime).append("\n");
+            }
         }
 
         return report.toString();

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java b/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java
index d214afa..79fe95d 100644
--- a/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java
+++ b/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java
@@ -56,19 +56,6 @@ public class MongoRyaShellIT extends RyaShellMongoITBase {
         // Ensure the connection was successful.
         assertTrue(connectResult.isSuccess());
     }
-    
-    @Test
-    public void connectMongo_noConnection() throws IOException {
-        final JLineShellComponent shell = getTestShell();
-        // Attempt to connect to a mongo instance.  The bad hostname should make this fail.
-        final String cmd =
-                RyaConnectionCommands.CONNECT_MONGO_CMD + " " +
-                        "--hostname badhostname " +
-                        "--port " + super.conf.getMongoPort();
-
-        final CommandResult rez = shell.executeCommand(cmd);
-        assertEquals(RuntimeException.class, rez.getException().getClass());
-    }
 
     @Test
     public void printConnectionDetails_notConnected() {


[7/8] incubator-rya git commit: RYA-303 Mongo PCJ Support. Closes #172.

Posted by ca...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java.orig
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java.orig b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java.orig
deleted file mode 100644
index 9311200..0000000
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java.orig
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * 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.
- */
-package org.apache.rya.indexing.accumulo;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.accumulo.core.client.AccumuloException;
-import org.apache.accumulo.core.client.AccumuloSecurityException;
-import org.apache.accumulo.core.client.BatchScanner;
-import org.apache.accumulo.core.client.BatchWriter;
-import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.Instance;
-import org.apache.accumulo.core.client.MultiTableBatchWriter;
-import org.apache.accumulo.core.client.Scanner;
-import org.apache.accumulo.core.client.TableExistsException;
-import org.apache.accumulo.core.client.TableNotFoundException;
-import org.apache.accumulo.core.client.ZooKeeperInstance;
-import org.apache.accumulo.core.client.admin.TableOperations;
-import org.apache.accumulo.core.client.mock.MockInstance;
-import org.apache.accumulo.core.security.Authorizations;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.mapreduce.JobContext;
-import org.apache.hadoop.util.ReflectionUtils;
-import org.apache.log4j.Logger;
-import org.apache.rya.accumulo.AccumuloRdfConfiguration;
-import org.apache.rya.accumulo.utils.ConnectorFactory;
-import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
-import org.apache.rya.api.instance.RyaDetails;
-import org.apache.rya.indexing.FilterFunctionOptimizer;
-import org.apache.rya.indexing.accumulo.entity.EntityCentricIndex;
-import org.apache.rya.indexing.accumulo.entity.EntityOptimizer;
-import org.apache.rya.indexing.accumulo.freetext.AccumuloFreeTextIndexer;
-import org.apache.rya.indexing.accumulo.freetext.LuceneTokenizer;
-import org.apache.rya.indexing.accumulo.freetext.Tokenizer;
-import org.apache.rya.indexing.accumulo.temporal.AccumuloTemporalIndexer;
-import org.apache.rya.indexing.entity.EntityIndexOptimizer;
-import org.apache.rya.indexing.entity.update.mongo.MongoEntityIndexer;
-import org.apache.rya.indexing.external.PrecomputedJoinIndexer;
-import org.apache.rya.indexing.mongodb.freetext.MongoFreeTextIndexer;
-import org.apache.rya.indexing.mongodb.temporal.MongoTemporalIndexer;
-import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
-import org.apache.rya.indexing.statement.metadata.matching.StatementMetadataOptimizer;
-import org.openrdf.model.URI;
-import org.openrdf.model.impl.URIImpl;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-
-/**
- * A set of configuration utils to read a Hadoop {@link Configuration} object and create Cloudbase/Accumulo objects.
- * Soon will deprecate this class.  Use installer for the set methods, use {@link RyaDetails} for the get methods.
- * New code must separate parameters that are set at Rya install time from that which is specific to the client.
- * Also Accumulo index tables are pushed down to the implementation and not configured in conf.
- */
-public class ConfigUtils {
-    private static final Logger logger = Logger.getLogger(ConfigUtils.class);
-
-    /**
-     * @Deprecated use {@link RdfCloudTripleStoreConfiguration#CONF_TBL_PREFIX} instead.
-     */
-    @Deprecated
-    public static final String CLOUDBASE_TBL_PREFIX = RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX;
-    
-    /**
-     * @Deprecated use {@link AccumuloRdfConfiguration#CLOUDBASE_INSTANCE} instead.
-     */
-    @Deprecated
-    public static final String CLOUDBASE_INSTANCE = AccumuloRdfConfiguration.CLOUDBASE_INSTANCE;
-    
-    /**
-     * @Deprecated use {@link AccumuloRdfConfiguration#CLOUDBASE_ZOOKEEPERS} instead.
-     */
-    @Deprecated
-    public static final String CLOUDBASE_ZOOKEEPERS = AccumuloRdfConfiguration.CLOUDBASE_ZOOKEEPERS;
-    
-    /**
-     * @Deprecated use {@link AccumuloRdfConfiguration#CLOUDBASE_USER} instead.
-     */
-    @Deprecated
-    public static final String CLOUDBASE_USER = AccumuloRdfConfiguration.CLOUDBASE_USER;
-    
-    /**
-     * @Deprecated use {@link AccumuloRdfConfiguration#CLOUDBASE_PASSWORD} instead.
-     */
-    @Deprecated
-    public static final String CLOUDBASE_PASSWORD = AccumuloRdfConfiguration.CLOUDBASE_PASSWORD;
-    /**
-     * @Deprecated use {@link RdfCloudTripleStoreConfiguration#CONF_QUERY_AUTH} instead.
-     */
-    @Deprecated
-    public static final String CLOUDBASE_AUTHS = RdfCloudTripleStoreConfiguration.CONF_QUERY_AUTH;
-
-    public static final String CLOUDBASE_WRITER_MAX_WRITE_THREADS = "sc.cloudbase.writer.maxwritethreads";
-    public static final String CLOUDBASE_WRITER_MAX_LATENCY = "sc.cloudbase.writer.maxlatency";
-    public static final String CLOUDBASE_WRITER_MAX_MEMORY = "sc.cloudbase.writer.maxmemory";
-
-    public static final String FREE_TEXT_QUERY_TERM_LIMIT = "sc.freetext.querytermlimit";
-
-    public static final String USE_FREETEXT = "sc.use_freetext";
-    public static final String USE_TEMPORAL = "sc.use_temporal";
-    public static final String USE_ENTITY = "sc.use_entity";
-    public static final String USE_PCJ = "sc.use_pcj";
-    public static final String USE_OPTIMAL_PCJ = "sc.use.optimal.pcj";
-    public static final String USE_PCJ_UPDATER_INDEX = "sc.use.updater";
-
-    public static final String FLUO_APP_NAME = "rya.indexing.pcj.fluo.fluoAppName";
-    public static final String USE_PCJ_FLUO_UPDATER = "rya.indexing.pcj.updater.fluo";
-    public static final String PCJ_STORAGE_TYPE = "rya.indexing.pcj.storageType";
-    public static final String PCJ_UPDATER_TYPE = "rya.indexing.pcj.updaterType";
-
-    public static final String USE_MOCK_INSTANCE = AccumuloRdfConfiguration.USE_MOCK_INSTANCE;
-
-    public static final String NUM_PARTITIONS = "sc.cloudbase.numPartitions";
-
-    private static final int WRITER_MAX_WRITE_THREADS = 1;
-    private static final long WRITER_MAX_LATNECY = Long.MAX_VALUE;
-    private static final long WRITER_MAX_MEMORY = 10000L;
-
-    public static final String DISPLAY_QUERY_PLAN = "query.printqueryplan";
-
-    public static final String FREETEXT_PREDICATES_LIST = "sc.freetext.predicates";
-    public static final String FREETEXT_DOC_NUM_PARTITIONS = "sc.freetext.numPartitions.text";
-    public static final String FREETEXT_TERM_NUM_PARTITIONS = "sc.freetext.numPartitions.term";
-
-    public static final String TOKENIZER_CLASS = "sc.freetext.tokenizer.class";
-
-    public static final String GEO_PREDICATES_LIST = "sc.geo.predicates";
-
-    public static final String TEMPORAL_PREDICATES_LIST = "sc.temporal.predicates";
-
-    public static final String USE_MONGO = "sc.useMongo";
-
-    public static boolean isDisplayQueryPlan(final Configuration conf) {
-        return conf.getBoolean(DISPLAY_QUERY_PLAN, false);
-    }
-
-    /**
-     * get a value from the configuration file and throw an exception if the
-     * value does not exist.
-     *
-     * @param conf
-     * @param key
-     * @return
-     */
-    private static String getStringCheckSet(final Configuration conf, final String key) {
-        final String value = conf.get(key);
-        requireNonNull(value, key + " not set");
-        return value;
-    }
-
-    /**
-     * @param conf
-     * @param tablename
-     * @return if the table was created
-     * @throws AccumuloException
-     * @throws AccumuloSecurityException
-     * @throws TableExistsException
-     */
-    public static boolean createTableIfNotExists(final Configuration conf, final String tablename)
-            throws AccumuloException, AccumuloSecurityException, TableExistsException {
-        final TableOperations tops = getConnector(conf).tableOperations();
-        if (!tops.exists(tablename)) {
-            logger.info("Creating table: " + tablename);
-            tops.create(tablename);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Lookup the table name prefix in the conf and throw an error if it is
-     * null. Future, get table prefix from RyaDetails -- the Rya instance name
-     * -- also getting info from the RyaDetails should happen within
-     * RyaSailFactory and not ConfigUtils.
-     * 
-     * @param conf
-     *            Rya configuration map where it extracts the prefix (instance
-     *            name)
-     * @return index table prefix corresponding to this Rya instance
-     */
-    public static String getTablePrefix(final Configuration conf) {
-        final String tablePrefix;
-        tablePrefix = conf.get(RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX);
-        requireNonNull(tablePrefix,
-                "Configuration key: " + RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX + " not set.  Cannot generate table name.");
-        return tablePrefix;
-    }
-
-    public static int getFreeTextTermLimit(final Configuration conf) {
-        return conf.getInt(FREE_TEXT_QUERY_TERM_LIMIT, 100);
-    }
-
-    public static Set<URI> getFreeTextPredicates(final Configuration conf) {
-        return getPredicates(conf, FREETEXT_PREDICATES_LIST);
-    }
-
-    public static Set<URI> getGeoPredicates(final Configuration conf) {
-        return getPredicates(conf, GEO_PREDICATES_LIST);
-    }
-
-    /**
-     * Used for indexing statements about date & time instances and intervals.
-     * 
-     * @param conf
-     * @return Set of predicate URI's whose objects should be date time
-     *         literals.
-     */
-    public static Set<URI> getTemporalPredicates(final Configuration conf) {
-        return getPredicates(conf, TEMPORAL_PREDICATES_LIST);
-    }
-
-    protected static Set<URI> getPredicates(final Configuration conf, final String confName) {
-        final String[] validPredicateStrings = conf.getStrings(confName, new String[] {});
-        final Set<URI> predicates = new HashSet<>();
-        for (final String prediateString : validPredicateStrings) {
-            predicates.add(new URIImpl(prediateString));
-        }
-        return predicates;
-    }
-
-    public static Tokenizer getFreeTextTokenizer(final Configuration conf) {
-        final Class<? extends Tokenizer> c = conf.getClass(TOKENIZER_CLASS, LuceneTokenizer.class, Tokenizer.class);
-        return ReflectionUtils.newInstance(c, conf);
-    }
-
-    public static BatchWriter createDefaultBatchWriter(final String tablename, final Configuration conf)
-            throws TableNotFoundException, AccumuloException, AccumuloSecurityException {
-        final Long DEFAULT_MAX_MEMORY = getWriterMaxMemory(conf);
-        final Long DEFAULT_MAX_LATENCY = getWriterMaxLatency(conf);
-        final Integer DEFAULT_MAX_WRITE_THREADS = getWriterMaxWriteThreads(conf);
-        final Connector connector = ConfigUtils.getConnector(conf);
-        return connector.createBatchWriter(tablename, DEFAULT_MAX_MEMORY, DEFAULT_MAX_LATENCY, DEFAULT_MAX_WRITE_THREADS);
-    }
-
-    public static MultiTableBatchWriter createMultitableBatchWriter(final Configuration conf)
-            throws AccumuloException, AccumuloSecurityException {
-        final Long DEFAULT_MAX_MEMORY = getWriterMaxMemory(conf);
-        final Long DEFAULT_MAX_LATENCY = getWriterMaxLatency(conf);
-        final Integer DEFAULT_MAX_WRITE_THREADS = getWriterMaxWriteThreads(conf);
-        final Connector connector = ConfigUtils.getConnector(conf);
-        return connector.createMultiTableBatchWriter(DEFAULT_MAX_MEMORY, DEFAULT_MAX_LATENCY, DEFAULT_MAX_WRITE_THREADS);
-    }
-
-    public static Scanner createScanner(final String tablename, final Configuration conf)
-            throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
-        final Connector connector = ConfigUtils.getConnector(conf);
-        final Authorizations auths = ConfigUtils.getAuthorizations(conf);
-        return connector.createScanner(tablename, auths);
-
-    }
-
-    public static BatchScanner createBatchScanner(final String tablename, final Configuration conf)
-            throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
-        final Connector connector = ConfigUtils.getConnector(conf);
-        final Authorizations auths = ConfigUtils.getAuthorizations(conf);
-        Integer numThreads = null;
-        if (conf instanceof RdfCloudTripleStoreConfiguration) {
-            numThreads = ((RdfCloudTripleStoreConfiguration) conf).getNumThreads();
-        } else {
-            numThreads = conf.getInt(RdfCloudTripleStoreConfiguration.CONF_NUM_THREADS, 2);
-        }
-        return connector.createBatchScanner(tablename, auths, numThreads);
-    }
-
-    public static int getWriterMaxWriteThreads(final Configuration conf) {
-        return conf.getInt(CLOUDBASE_WRITER_MAX_WRITE_THREADS, WRITER_MAX_WRITE_THREADS);
-    }
-
-    public static long getWriterMaxLatency(final Configuration conf) {
-        return conf.getLong(CLOUDBASE_WRITER_MAX_LATENCY, WRITER_MAX_LATNECY);
-    }
-
-    public static long getWriterMaxMemory(final Configuration conf) {
-        return conf.getLong(CLOUDBASE_WRITER_MAX_MEMORY, WRITER_MAX_MEMORY);
-    }
-
-    public static String getUsername(final JobContext job) {
-        return getUsername(job.getConfiguration());
-    }
-
-    /**
-     * Get the Accumulo username from the configuration object that is meant to
-     * be used when connecting a {@link Connector} to Accumulo.
-     *
-     * @param conf - The configuration object that will be interrogated. (not null)
-     * @return The username if one could be found; otherwise {@code null}.
-     */
-    public static String getUsername(final Configuration conf) {
-        return new AccumuloRdfConfiguration(conf).getUsername();
-    }
-
-    public static Authorizations getAuthorizations(final JobContext job) {
-        return getAuthorizations(job.getConfiguration());
-    }
-
-    public static Authorizations getAuthorizations(final Configuration conf) {
-        final String authString = conf.get(RdfCloudTripleStoreConfiguration.CONF_QUERY_AUTH, "");
-        if (authString.isEmpty()) {
-            return new Authorizations();
-        }
-        return new Authorizations(authString.split(","));
-    }
-
-    public static Instance getInstance(final JobContext job) {
-        return getInstance(job.getConfiguration());
-    }
-
-    /**
-     * Create an {@link Instance} that may be used to create {@link Connector}s
-     * to Accumulo. If the configuration has the {@link #USE_MOCK_INSTANCE} flag
-     * set, then the instance will be be a {@link MockInstance} instead of a
-     * Zookeeper backed instance.
-     *
-     * @param conf - The configuration object that will be interrogated. (not null)
-     * @return The {@link Instance} that may be used to connect to Accumulo.
-     */
-    public static Instance getInstance(final Configuration conf) {
-        // Pull out the Accumulo specific configuration values.
-        final AccumuloRdfConfiguration accConf = new AccumuloRdfConfiguration(conf);
-        String instanceName = accConf.getInstanceName();
-        String zoookeepers = accConf.getZookeepers();
-
-        // Create an Instance a mock if the mock flag is set.
-        if (useMockInstance(conf)) {
-            return new MockInstance(instanceName);
-        }
-
-        // Otherwise create an Instance to a Zookeeper managed instance of Accumulo.
-        return new ZooKeeperInstance(instanceName, zoookeepers);
-    }
-
-    public static String getPassword(final JobContext job) {
-        return getPassword(job.getConfiguration());
-    }
-
-    /**
-     * Get the Accumulo password from the configuration object that is meant to
-     * be used when connecting a {@link Connector} to Accumulo.
-     *
-     * @param conf - The configuration object that will be interrogated. (not null)
-     * @return The password if one could be found; otherwise an empty string.
-     */
-    public static String getPassword(final Configuration conf) {
-        return new AccumuloRdfConfiguration(conf).getPassword();
-    }
-
-    public static Connector getConnector(final JobContext job) throws AccumuloException, AccumuloSecurityException {
-        return getConnector(job.getConfiguration());
-    }
-
-    /**
-     * Create an Accumulo {@link Connector} using the configured connection information.
-     * If the connection information  points to a mock instance of Accumulo, then the
-     * {@link #USE_MOCK_INSTANCE} flag must be set.
-     *
-     * @param conf - Configures how the connector will be built. (not null)
-     * @return A {@link Connector} that may be used to interact with the configured Accumulo instance.
-     * @throws AccumuloException The connector couldn't be created because of an Accumulo problem.
-     * @throws AccumuloSecurityException The connector couldn't be created because of an Accumulo security violation.
-     */
-    public static Connector getConnector(final Configuration conf) throws AccumuloException, AccumuloSecurityException {
-        return ConnectorFactory.connect( new AccumuloRdfConfiguration(conf) );
-    }
-
-    /**
-     * Indicates that a Mock instance of Accumulo is being used to back the Rya instance.
-     *
-     * @param conf - The configuration object that will be interrogated. (not null)
-     * @return {@code true} if the Rya instance is backed by a mock Accumulo; otherwise {@code false}.
-     */
-    public static boolean useMockInstance(final Configuration conf) {
-        return new AccumuloRdfConfiguration(conf).useMockInstance();
-    }
-
-    protected static int getNumPartitions(final Configuration conf) {
-        return conf.getInt(NUM_PARTITIONS, 25);
-    }
-
-    public static int getFreeTextDocNumPartitions(final Configuration conf) {
-        return conf.getInt(FREETEXT_DOC_NUM_PARTITIONS, getNumPartitions(conf));
-    }
-
-    public static int getFreeTextTermNumPartitions(final Configuration conf) {
-        return conf.getInt(FREETEXT_TERM_NUM_PARTITIONS, getNumPartitions(conf));
-    }
-
-    public static boolean getUseFreeText(final Configuration conf) {
-        return conf.getBoolean(USE_FREETEXT, false);
-    }
-
-    public static boolean getUseTemporal(final Configuration conf) {
-        return conf.getBoolean(USE_TEMPORAL, false);
-    }
-
-    public static boolean getUseEntity(final Configuration conf) {
-        return conf.getBoolean(USE_ENTITY, false);
-    }
-
-    public static boolean getUsePCJ(final Configuration conf) {
-        return conf.getBoolean(USE_PCJ, false);
-    }
-
-    public static boolean getUseOptimalPCJ(final Configuration conf) {
-        return conf.getBoolean(USE_OPTIMAL_PCJ, false);
-    }
-
-    public static boolean getUsePcjUpdaterIndex(final Configuration conf) {
-        return conf.getBoolean(USE_PCJ_UPDATER_INDEX, false);
-    }
-
-
-    /**
-     * @return The name of the Fluo Application this instance of RYA is using to
-     *         incrementally update PCJs.
-     */
-    // TODO delete this eventually and use Details table
-    public Optional<String> getFluoAppName(final Configuration conf) {
-        return Optional.fromNullable(conf.get(FLUO_APP_NAME));
-    }
-
-
-    public static boolean getUseMongo(final Configuration conf) {
-        return conf.getBoolean(USE_MONGO, false);
-    }
-
-
-    public static void setIndexers(final RdfCloudTripleStoreConfiguration conf) {
-
-        final List<String> indexList = Lists.newArrayList();
-        final List<String> optimizers = Lists.newArrayList();
-
-        boolean useFilterIndex = false;
-
-        if (ConfigUtils.getUseMongo(conf)) {
-            if (getUseFreeText(conf)) {
-                indexList.add(MongoFreeTextIndexer.class.getName());
-                useFilterIndex = true;
-            }
-
-            if (getUseEntity(conf)) {
-                indexList.add(MongoEntityIndexer.class.getName());
-                optimizers.add(EntityIndexOptimizer.class.getName());
-            }
-
-            if (getUseTemporal(conf)) {
-                indexList.add(MongoTemporalIndexer.class.getName());
-                useFilterIndex = true;
-            }
-        } else {
-        	if (getUsePCJ(conf) || getUseOptimalPCJ(conf)) {
-        		conf.setPcjOptimizer(PCJOptimizer.class);
-        	}
-
-            if (getUsePcjUpdaterIndex(conf)) {
-                indexList.add(PrecomputedJoinIndexer.class.getName());
-            }
-
-            if (getUseFreeText(conf)) {
-                indexList.add(AccumuloFreeTextIndexer.class.getName());
-                useFilterIndex = true;
-            }
-
-            if (getUseTemporal(conf)) {
-                indexList.add(AccumuloTemporalIndexer.class.getName());
-                useFilterIndex = true;
-            }
-
-            if (getUseEntity(conf)) {
-                indexList.add(EntityCentricIndex.class.getName());
-                optimizers.add(EntityOptimizer.class.getName());
-            }
-        }
-
-        if (useFilterIndex) {
-            optimizers.add(FilterFunctionOptimizer.class.getName());
-        }
-
-        if (conf.getUseStatementMetadata()) {
-            optimizers.add(StatementMetadataOptimizer.class.getName());
-        }
-
-<<<<<<< HEAD
-        conf.setStrings(AccumuloRdfConfiguration.CONF_ADDITIONAL_INDEXERS, indexList.toArray(new String[] {}));
-        conf.setStrings(RdfCloudTripleStoreConfiguration.CONF_OPTIMIZERS, optimizers.toArray(new String[] {}));
-    }
-}
-=======
-        final String[] existingIndexers = conf.getStrings(AccumuloRdfConfiguration.CONF_ADDITIONAL_INDEXERS);
-        if(existingIndexers != null ) {
-            for(final String idx : existingIndexers) {
-                indexList.add(idx);
-            }
-        }
-
-        final String[] existingOptimizers = conf.getStrings(RdfCloudTripleStoreConfiguration.CONF_OPTIMIZERS);
-        if(existingOptimizers != null ) {
-            for(final String opt : existingOptimizers) {
-                optimizers.add(opt);
-            }
-        }
-
-        conf.setStrings(AccumuloRdfConfiguration.CONF_ADDITIONAL_INDEXERS, indexList.toArray(new String[]{}));
-        conf.setStrings(RdfCloudTripleStoreConfiguration.CONF_OPTIMIZERS, optimizers.toArray(new String[]{}));
-    }
-
-
-
-}
->>>>>>> RYA-236 Changes to other indexers

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/external/PrecomputedJoinIndexerConfig.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/external/PrecomputedJoinIndexerConfig.java b/extras/indexing/src/main/java/org/apache/rya/indexing/external/PrecomputedJoinIndexerConfig.java
index d73e180..4faf4a0 100644
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/external/PrecomputedJoinIndexerConfig.java
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/external/PrecomputedJoinIndexerConfig.java
@@ -47,7 +47,11 @@ public class PrecomputedJoinIndexerConfig {
         /**
          * Stores each PCJ within an Accumulo table.
          */
-        ACCUMULO;
+        ACCUMULO,
+        /**
+         * Stores each PCJ within a MongoDB collection.
+         */
+        MONGO;
     }
 
     /**
@@ -106,8 +110,6 @@ public class PrecomputedJoinIndexerConfig {
         return Optional.fromNullable(updaterType);
     }
 
-
-
     public boolean getUseFluoUpdater() {
     	return config.getBoolean(ConfigUtils.USE_PCJ_UPDATER_INDEX, false);
     }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/mongodb/pcj/MongoPcjIndexSetProvider.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/mongodb/pcj/MongoPcjIndexSetProvider.java b/extras/indexing/src/main/java/org/apache/rya/indexing/mongodb/pcj/MongoPcjIndexSetProvider.java
new file mode 100644
index 0000000..d3fa07e
--- /dev/null
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/mongodb/pcj/MongoPcjIndexSetProvider.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+package org.apache.rya.indexing.mongodb.pcj;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.rya.api.instance.RyaDetailsRepository;
+import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.pcj.matching.provider.AbstractPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjDocuments;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjStorage;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
+import org.apache.rya.mongodb.instance.MongoRyaInstanceDetailsRepository;
+import org.openrdf.query.MalformedQueryException;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.mongodb.MongoClient;
+
+/**
+ * Implementation of {@link AbstractPcjIndexSetProvider} for MongoDB.
+ */
+public class MongoPcjIndexSetProvider extends AbstractPcjIndexSetProvider {
+    /**
+     * Creates a new {@link MongoPcjIndexSetProvider}.
+     * @param conf - The configuration for this provider. (not null)
+     */
+    public MongoPcjIndexSetProvider(final StatefulMongoDBRdfConfiguration conf) {
+        super(conf);
+    }
+
+    /**
+     * Creates a new {@link MongoPcjIndexSetProvider}.
+     * @param conf - The configuration for this provider.
+     * @param indices - The predefined indicies on this provider.
+     * @param client - The {@link MongoClient} used to connect to mongo.
+     */
+    public MongoPcjIndexSetProvider(final StatefulMongoDBRdfConfiguration conf, final List<ExternalTupleSet> indices) {
+        super(conf, indices);
+    }
+
+    @Override
+    protected List<ExternalTupleSet> getIndices() throws PcjIndexSetException {
+        try {
+            final StatefulMongoDBRdfConfiguration mongoConf = (StatefulMongoDBRdfConfiguration) conf;
+            final MongoClient client = mongoConf.getMongoClient();
+            final MongoPcjDocuments pcjDocs = new MongoPcjDocuments(client, mongoConf.getRyaInstanceName());
+            List<String> documents = null;
+
+            documents = mongoConf.getPcjTables();
+            // this maps associates pcj document name with pcj sparql query
+            final Map<String, String> indexDocuments = Maps.newLinkedHashMap();
+
+            try(final PrecomputedJoinStorage storage = new MongoPcjStorage(client, mongoConf.getRyaInstanceName())) {
+
+                final boolean docsProvided = documents != null && !documents.isEmpty();
+
+                if (docsProvided) {
+                    // if tables provided, associate table name with sparql
+                    for (final String doc : documents) {
+                        indexDocuments.put(doc, storage.getPcjMetadata(doc).getSparql());
+                    }
+                } else if (hasRyaDetails()) {
+                    // If this is a newer install of Rya, and it has PCJ Details, then
+                    // use those.
+                    final List<String> ids = storage.listPcjs();
+                    for (final String pcjId : ids) {
+                        indexDocuments.put(pcjId, storage.getPcjMetadata(pcjId).getSparql());
+                    }
+                } else {
+                    // Otherwise figure it out by getting document IDs.
+                    documents = pcjDocs.listPcjDocuments();
+                    for (final String pcjId : documents) {
+                        if (pcjId.startsWith("INDEX")) {
+                            indexDocuments.put(pcjId, pcjDocs.getPcjMetadata(pcjId).getSparql());
+                        }
+                    }
+                }
+            }
+
+            final List<ExternalTupleSet> index = Lists.newArrayList();
+            if (indexDocuments.isEmpty()) {
+                log.info("No Index found");
+            } else {
+                for (final String pcjID : indexDocuments.keySet()) {
+                    final String indexSparqlString = indexDocuments.get(pcjID);
+                    index.add(new MongoPcjQueryNode(indexSparqlString, pcjID, pcjDocs));
+                }
+            }
+            return index;
+        } catch (final PCJStorageException | MalformedQueryException e) {
+            throw new PcjIndexSetException("Failed to get indicies for this PCJ index.", e);
+        }
+    }
+
+    private boolean hasRyaDetails() {
+        final StatefulMongoDBRdfConfiguration mongoConf = (StatefulMongoDBRdfConfiguration) conf;
+        final RyaDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(mongoConf.getMongoClient(), mongoConf.getRyaInstanceName());
+        try {
+            detailsRepo.getRyaInstanceDetails();
+            return true;
+        } catch (final RyaDetailsRepositoryException e) {
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/mongodb/pcj/MongoPcjQueryNode.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/mongodb/pcj/MongoPcjQueryNode.java b/extras/indexing/src/main/java/org/apache/rya/indexing/mongodb/pcj/MongoPcjQueryNode.java
new file mode 100644
index 0000000..c03ee99
--- /dev/null
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/mongodb/pcj/MongoPcjQueryNode.java
@@ -0,0 +1,167 @@
+/**
+ * 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.
+ */
+package org.apache.rya.indexing.mongodb.pcj;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.log4j.Logger;
+import org.apache.rya.api.utils.CloseableIterator;
+import org.apache.rya.api.utils.IteratorWrapper;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.external.tupleSet.ParsedQueryUtil;
+import org.apache.rya.indexing.pcj.matching.PCJOptimizerUtilities;
+import org.apache.rya.indexing.pcj.storage.PcjException;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjDocuments;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
+import org.apache.rya.rdftriplestore.evaluation.ExternalBatchingIterator;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.MalformedQueryException;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.query.algebra.Projection;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.parser.ParsedTupleQuery;
+import org.openrdf.query.parser.sparql.SPARQLParser;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+import edu.umd.cs.findbugs.annotations.DefaultAnnotation;
+import edu.umd.cs.findbugs.annotations.NonNull;
+import info.aduna.iteration.CloseableIteration;
+
+/**
+ * Indexing Node for PCJs expressions to be inserted into execution plans.
+ */
+@DefaultAnnotation(NonNull.class)
+public class MongoPcjQueryNode extends ExternalTupleSet implements ExternalBatchingIterator {
+    private static final Logger log = Logger.getLogger(MongoPcjQueryNode.class);
+    private final String pcjId;
+    private final MongoPcjDocuments pcjDocs;
+
+    /**
+     * Creates a new {@link MongoPcjQueryNode}.
+     *
+     * @param sparql - sparql query whose results will be stored in PCJ document. (not empty of null)
+     * @param pcjId - name of an existing PCJ. (not empty or null)
+     * @param pcjDocs - {@link MongoPcjDocuments} used to maintain PCJs in mongo. (not null)
+     *
+     * @throws MalformedQueryException - The SPARQL query needs to contain a projection.
+     */
+    public MongoPcjQueryNode(final String sparql, final String pcjId, final MongoPcjDocuments pcjDocs) throws MalformedQueryException {
+        checkArgument(!Strings.isNullOrEmpty(sparql));
+        checkArgument(!Strings.isNullOrEmpty(pcjId));
+        this.pcjDocs = checkNotNull(pcjDocs);
+        this.pcjId = pcjId;
+        final SPARQLParser sp = new SPARQLParser();
+        final ParsedTupleQuery pq = (ParsedTupleQuery) sp.parseQuery(sparql, null);
+        final TupleExpr te = pq.getTupleExpr();
+        Preconditions.checkArgument(PCJOptimizerUtilities.isPCJValid(te), "TupleExpr is an invalid PCJ.");
+
+        final Optional<Projection> projection = new ParsedQueryUtil().findProjection(pq);
+        if (!projection.isPresent()) {
+            throw new MalformedQueryException("SPARQL query '" + sparql + "' does not contain a Projection.");
+        }
+        setProjectionExpr(projection.get());
+    }
+
+    /**
+     * Creates a new {@link MongoPcjQueryNode}.
+     *
+     * @param conf - configuration to use to connect to mongo. (not null)
+     * @param pcjId - name of an existing PCJ. (not empty or null)
+     */
+    public MongoPcjQueryNode(final Configuration conf, final String pcjId) {
+        checkNotNull(conf);
+        checkArgument(conf instanceof StatefulMongoDBRdfConfiguration,
+                "The configuration must be a StatefulMongoDBRdfConfiguration, found: " + conf.getClass().getSimpleName());
+        checkArgument(!Strings.isNullOrEmpty(pcjId));
+        final StatefulMongoDBRdfConfiguration statefulConf = (StatefulMongoDBRdfConfiguration) conf;
+        pcjDocs = new MongoPcjDocuments(statefulConf.getMongoClient(), statefulConf.getRyaInstanceName());
+        this.pcjId = checkNotNull(pcjId);
+    }
+
+    /**
+     * returns size of table for query planning
+     */
+    @Override
+    public double cardinality() {
+        double cardinality = 0;
+        try {
+            cardinality = pcjDocs.getPcjMetadata(pcjId).getCardinality();
+        } catch (final PcjException e) {
+            log.error("The PCJ has not been created, so has no cardinality.", e);
+        }
+        return cardinality;
+    }
+
+    @Override
+    public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(final BindingSet bindingset)
+            throws QueryEvaluationException {
+        return this.evaluate(Collections.singleton(bindingset));
+    }
+
+    @Override
+    public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(final Collection<BindingSet> bindingset)
+            throws QueryEvaluationException {
+
+        if (bindingset.isEmpty()) {
+            return new IteratorWrapper<BindingSet, QueryEvaluationException>(new HashSet<BindingSet>().iterator());
+        }
+        final CloseableIterator<BindingSet> iter = pcjDocs.getResults(pcjId, bindingset);
+        return new CloseableIteration<BindingSet, QueryEvaluationException>() {
+            @Override
+            public boolean hasNext() throws QueryEvaluationException {
+                return iter.hasNext();
+            }
+
+            @Override
+            public BindingSet next() throws QueryEvaluationException {
+                final BindingSet bs = iter.next();
+                return bs;
+            }
+
+            @Override
+            public void remove() throws QueryEvaluationException {
+                iter.remove();
+            }
+
+            @Override
+            public void close() throws QueryEvaluationException {
+                try {
+                    iter.close();
+                } catch (final Exception e) {
+                    throw new QueryEvaluationException(e.getMessage(), e);
+                }
+            }
+        };
+    }
+
+    @Override
+    public String getSignature() {
+        return "(Mongo PcjQueryNode) " + Joiner.on(", ").join(super.getTupleExpr().getProjectionElemList().getElements()).replaceAll("\\s+", " ");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/AccumuloIndexSetProvider.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/AccumuloIndexSetProvider.java b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/AccumuloIndexSetProvider.java
deleted file mode 100644
index 4a15665..0000000
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/AccumuloIndexSetProvider.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- * 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.
- */
-package org.apache.rya.indexing.pcj.matching;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-import org.apache.accumulo.core.client.AccumuloException;
-import org.apache.accumulo.core.client.AccumuloSecurityException;
-import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.TableNotFoundException;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.log4j.Logger;
-import org.apache.rya.accumulo.instance.AccumuloRyaInstanceDetailsRepository;
-import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
-import org.apache.rya.api.instance.RyaDetailsRepository;
-import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException;
-import org.apache.rya.indexing.IndexPlanValidator.IndexedExecutionPlanGenerator;
-import org.apache.rya.indexing.IndexPlanValidator.ValidIndexCombinationGenerator;
-import org.apache.rya.indexing.accumulo.ConfigUtils;
-import org.apache.rya.indexing.external.matching.ExternalSetProvider;
-import org.apache.rya.indexing.external.matching.QuerySegment;
-import org.apache.rya.indexing.external.tupleSet.AccumuloIndexSet;
-import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
-import org.apache.rya.indexing.pcj.storage.PcjException;
-import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage;
-import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjStorage;
-import org.apache.rya.indexing.pcj.storage.accumulo.PcjTableNameFactory;
-import org.apache.rya.indexing.pcj.storage.accumulo.PcjTables;
-import org.openrdf.query.MalformedQueryException;
-import org.openrdf.query.QueryEvaluationException;
-import org.openrdf.query.algebra.TupleExpr;
-import org.openrdf.sail.SailException;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/**
- * Implementation of {@link ExternalSetProvider} that provides {@link ExternalTupleSet}s.
- * This provider uses either user specified Accumulo configuration information or user a specified
- * List of ExternalTupleSets to populate an internal cache of ExternalTupleSets.  If Accumulo configuration
- * is provided, the provider connects to an instance of RyaDetails and populates the cache with
- * PCJs registered in RyaDetails.
- *
- */
-public class AccumuloIndexSetProvider implements ExternalSetProvider<ExternalTupleSet> {
-
-    private static final Logger log = Logger.getLogger(ExternalSetProvider.class);
-    private static final PCJToSegmentConverter converter = new PCJToSegmentConverter();
-    private List<ExternalTupleSet> indexCache;
-    private final Configuration conf;
-    private boolean init = false;
-
-    public AccumuloIndexSetProvider(final Configuration conf) {
-        this.conf = Objects.requireNonNull(conf);
-    }
-
-    public AccumuloIndexSetProvider(final Configuration conf, final List<ExternalTupleSet> indices) {
-        this(conf);
-        indexCache = indices;
-        init = true;
-    }
-
-    /**
-     *
-     * @return - size of underlying PCJ cache
-     * @throws Exception
-     */
-    public int size() throws Exception {
-        if(!init) {
-            indexCache = PCJOptimizerUtilities.getValidPCJs(getAccIndices());
-            init = true;
-        }
-        return indexCache.size();
-    }
-
-    /**
-     * @param segment - QuerySegment used to get relevant queries form index cache for matching
-     * @return List of PCJs for matching
-     */
-    @Override
-    public List<ExternalTupleSet> getExternalSets(final QuerySegment<ExternalTupleSet> segment) {
-        try {
-            if(!init) {
-                indexCache = PCJOptimizerUtilities.getValidPCJs(getAccIndices());
-                init = true;
-            }
-            final TupleExpr query = segment.getQuery().getTupleExpr();
-            final IndexedExecutionPlanGenerator iep = new IndexedExecutionPlanGenerator(query, indexCache);
-            final List<ExternalTupleSet> pcjs = iep.getNormalizedIndices();
-            final List<ExternalTupleSet> tuples = new ArrayList<>();
-            for (final ExternalTupleSet tuple: pcjs) {
-                final QuerySegment<ExternalTupleSet> pcj = converter.setToSegment(tuple);
-                if (segment.containsQuerySegment(pcj)) {
-                    tuples.add(tuple);
-                }
-            }
-            return tuples;
-
-        } catch (final Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * @param segment - QuerySegment used to get relevant queries form index cache for matching
-     *
-     * @return Iterator of Lists (combos) of PCJs used to build an optimal query plan
-     */
-    @Override
-    public Iterator<List<ExternalTupleSet>> getExternalSetCombos(final QuerySegment<ExternalTupleSet> segment) {
-        final ValidIndexCombinationGenerator comboGen = new ValidIndexCombinationGenerator(segment.getOrderedNodes());
-        return comboGen.getValidIndexCombos(getExternalSets(segment));
-    }
-
-    /**
-     *
-     *
-     * @param conf
-     *            - client configuration
-     *
-     * @return - list of {@link ExternalTupleSet}s or PCJs that are either
-     *         specified by user in Configuration or exist in system.
-     *
-     * @throws MalformedQueryException
-     * @throws SailException
-     * @throws QueryEvaluationException
-     * @throws TableNotFoundException
-     * @throws AccumuloException
-     * @throws AccumuloSecurityException
-     * @throws PcjException
-     */
-    private List<ExternalTupleSet> getAccIndices() throws Exception {
-
-        Objects.requireNonNull(conf);
-        final String tablePrefix = Objects.requireNonNull(conf.get(RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX));
-        final Connector conn = Objects.requireNonNull(ConfigUtils.getConnector(conf));
-        List<String> tables = null;
-
-        if (conf instanceof RdfCloudTripleStoreConfiguration) {
-            tables = ((RdfCloudTripleStoreConfiguration) conf).getPcjTables();
-        }
-        // this maps associates pcj table name with pcj sparql query
-        final Map<String, String> indexTables = Maps.newLinkedHashMap();
-
-        try(final PrecomputedJoinStorage storage = new AccumuloPcjStorage(conn, tablePrefix)) {
-            final PcjTableNameFactory pcjFactory = new PcjTableNameFactory();
-
-            final boolean tablesProvided = tables != null && !tables.isEmpty();
-
-            if (tablesProvided) {
-                // if tables provided, associate table name with sparql
-                for (final String table : tables) {
-                    indexTables.put(table, storage.getPcjMetadata(pcjFactory.getPcjId(table)).getSparql());
-                }
-            } else if (hasRyaDetails(tablePrefix, conn)) {
-                // If this is a newer install of Rya, and it has PCJ Details, then
-                // use those.
-                final List<String> ids = storage.listPcjs();
-                for (final String id : ids) {
-                    indexTables.put(pcjFactory.makeTableName(tablePrefix, id), storage.getPcjMetadata(id).getSparql());
-                }
-            } else {
-                // Otherwise figure it out by scanning tables.
-                final PcjTables pcjTables = new PcjTables();
-                for (final String table : conn.tableOperations().list()) {
-                    if (table.startsWith(tablePrefix + "INDEX")) {
-                        indexTables.put(table, pcjTables.getPcjMetadata(conn, table).getSparql());
-                    }
-                }
-            }
-        }
-
-        // use table name sparql map (indexTables) to create {@link
-        // AccumuloIndexSet}
-        final List<ExternalTupleSet> index = Lists.newArrayList();
-        if (indexTables.isEmpty()) {
-            log.info("No Index found");
-        } else {
-            for (final String table : indexTables.keySet()) {
-                final String indexSparqlString = indexTables.get(table);
-                index.add(new AccumuloIndexSet(indexSparqlString, conf, table));
-            }
-        }
-
-
-        return index;
-    }
-
-    private static boolean hasRyaDetails(final String ryaInstanceName, final Connector conn) {
-        final RyaDetailsRepository detailsRepo = new AccumuloRyaInstanceDetailsRepository(conn, ryaInstanceName);
-        try {
-            detailsRepo.getRyaInstanceDetails();
-            return true;
-        } catch (final RyaDetailsRepositoryException e) {
-            return false;
-        }
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizer.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizer.java b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizer.java
index 75b48b4..8067a85 100644
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizer.java
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizer.java
@@ -33,6 +33,10 @@ import org.apache.rya.indexing.external.matching.QueryNodeListRater;
 import org.apache.rya.indexing.external.matching.QuerySegment;
 import org.apache.rya.indexing.external.matching.TopOfQueryFilterRelocator;
 import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.mongodb.pcj.MongoPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.matching.provider.AbstractPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.Dataset;
 import org.openrdf.query.algebra.QueryModelNode;
@@ -58,29 +62,32 @@ import com.google.common.base.Optional;;
  */
 public class PCJOptimizer extends AbstractExternalSetOptimizer<ExternalTupleSet>implements Configurable {
     private static final PCJExternalSetMatcherFactory factory = new PCJExternalSetMatcherFactory();
-    private AccumuloIndexSetProvider provider;
+    private AbstractPcjIndexSetProvider provider;
     private Configuration conf;
     private boolean init = false;
 
     public PCJOptimizer() {}
 
     public PCJOptimizer(final Configuration conf) {
-       setConf(conf);
+        setConf(conf);
     }
 
     /**
      * This constructor is designed to be used for testing.  A more typical use
      * pattern is for a user to specify Accumulo connection details in a Configuration
      * file so that PCJs can be retrieved by an AccumuloIndexSetProvider.
-     * 
-     * @param indices - user specified PCJs to match to query
+     *
+     * @param indices - user specified PCJs to match to query. (not null)
      * @param useOptimalPcj - optimize PCJ combos for matching
+     * @param provider - The provider to use in this optimizer. (not null)
      */
-    public PCJOptimizer(final List<ExternalTupleSet> indices, final boolean useOptimalPcj) {
+    public PCJOptimizer(final List<ExternalTupleSet> indices, final boolean useOptimalPcj,
+            final AbstractPcjIndexSetProvider provider) {
         checkNotNull(indices);
+        checkNotNull(provider);
         conf = new Configuration();
-        this.useOptimal = useOptimalPcj;
-        provider = new AccumuloIndexSetProvider(conf, indices);
+        useOptimal = useOptimalPcj;
+        this.provider = provider;
         init = true;
     }
 
@@ -90,9 +97,14 @@ public class PCJOptimizer extends AbstractExternalSetOptimizer<ExternalTupleSet>
         if (!init) {
             try {
                 this.conf = conf;
-                this.useOptimal = ConfigUtils.getUseOptimalPCJ(conf);
-                provider = new AccumuloIndexSetProvider(conf);
-            } catch (Exception e) {
+                useOptimal = ConfigUtils.getUseOptimalPCJ(conf);
+                if (conf instanceof StatefulMongoDBRdfConfiguration) {
+                    final StatefulMongoDBRdfConfiguration mongoConf = (StatefulMongoDBRdfConfiguration) conf;
+                    provider = new MongoPcjIndexSetProvider(mongoConf);
+                } else {
+                    provider = new AccumuloIndexSetProvider(conf);
+                }
+            } catch (final Exception e) {
                 throw new Error(e);
             }
             init = true;
@@ -124,14 +136,14 @@ public class PCJOptimizer extends AbstractExternalSetOptimizer<ExternalTupleSet>
             } else {
                 return;
             }
-        } catch (Exception e) {
-            throw new RuntimeException("Could not populate Accumulo Index Cache.");
+        } catch (final Exception e) {
+            throw new RuntimeException("Could not populate Index Cache.", e);
         }
     }
 
 
     @Override
-    protected ExternalSetMatcher<ExternalTupleSet> getMatcher(QuerySegment<ExternalTupleSet> segment) {
+    protected ExternalSetMatcher<ExternalTupleSet> getMatcher(final QuerySegment<ExternalTupleSet> segment) {
         return factory.getMatcher(segment);
     }
 
@@ -141,7 +153,7 @@ public class PCJOptimizer extends AbstractExternalSetOptimizer<ExternalTupleSet>
     }
 
     @Override
-    protected Optional<QueryNodeListRater> getNodeListRater(QuerySegment<ExternalTupleSet> segment) {
+    protected Optional<QueryNodeListRater> getNodeListRater(final QuerySegment<ExternalTupleSet> segment) {
         return Optional.of(new BasicRater(segment.getOrderedNodes()));
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerUtilities.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerUtilities.java b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerUtilities.java
index 1ad03b6..09a2706 100644
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerUtilities.java
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/PCJOptimizerUtilities.java
@@ -27,7 +27,6 @@ import java.util.Set;
 import org.apache.rya.indexing.external.matching.QuerySegment;
 import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.rya.indexing.pcj.matching.QueryVariableNormalizer.VarCollector;
-
 import org.openrdf.query.algebra.Difference;
 import org.openrdf.query.algebra.EmptySet;
 import org.openrdf.query.algebra.Filter;
@@ -61,7 +60,7 @@ public class PCJOptimizerUtilities {
 	 * @param node - node to be checked for validity
 	 * @return - true if valid and false otherwise
 	 */
-	public static boolean isPCJValid(TupleExpr node) {
+	public static boolean isPCJValid(final TupleExpr node) {
 
 		final ValidQueryVisitor vqv = new ValidQueryVisitor();
 		node.visit(vqv);
@@ -91,16 +90,16 @@ public class PCJOptimizerUtilities {
 	 * @param node - PCJ {@link ExternalTupleSet} index node to be checked for validity
 	 * @return - true if valid and false otherwise
 	 */
-	public static boolean isPCJValid(ExternalTupleSet node) {
+	public static boolean isPCJValid(final ExternalTupleSet node) {
 		return isPCJValid(node.getTupleExpr());
 	}
 
 	public static List<ExternalTupleSet> getValidPCJs(
-			List<ExternalTupleSet> pcjs) {
+			final List<ExternalTupleSet> pcjs) {
 
-		Iterator<ExternalTupleSet> iterator = pcjs.iterator();
+		final Iterator<ExternalTupleSet> iterator = pcjs.iterator();
 		while (iterator.hasNext()) {
-			ExternalTupleSet pcj = iterator.next();
+			final ExternalTupleSet pcj = iterator.next();
 			if (!isPCJValid(pcj)) {
 				iterator.remove();
 			}
@@ -109,8 +108,8 @@ public class PCJOptimizerUtilities {
 	}
 
 
-	public static Projection getProjection(TupleExpr te) {
-		ProjectionVisitor visitor = new ProjectionVisitor();
+	public static Projection getProjection(final TupleExpr te) {
+		final ProjectionVisitor visitor = new ProjectionVisitor();
 		te.visit(visitor);
 		return visitor.node;
 	}
@@ -120,7 +119,7 @@ public class PCJOptimizerUtilities {
 		Projection node = null;
 
 		@Override
-		public void meet(Projection node) {
+		public void meet(final Projection node) {
 			this.node = node;
 		}
 	}
@@ -131,13 +130,13 @@ public class PCJOptimizerUtilities {
 	 *            - filters to be pushed down into next {@link QuerySegment}, or
 	 *            as far down as binding variable names permit.
 	 */
-	public static void relocateFilters(Set<Filter> filters) {
-		for (Filter filter : filters) {
+	public static void relocateFilters(final Set<Filter> filters) {
+		for (final Filter filter : filters) {
 			FilterRelocator.relocate(filter);
 		}
 	}
 
-	private static Set<String> getVarNames(Collection<QueryModelNode> nodes) {
+	private static Set<String> getVarNames(final Collection<QueryModelNode> nodes) {
 		List<String> tempVars;
 		final Set<String> nodeVarNames = Sets.newHashSet();
 
@@ -159,8 +158,8 @@ public class PCJOptimizerUtilities {
 			QueryModelVisitorBase<RuntimeException> {
 
 		private boolean isValid = true;
-		private Set<QueryModelNode> filterSet = Sets.newHashSet();
-		private Set<QueryModelNode> spSet = Sets.newHashSet();
+		private final Set<QueryModelNode> filterSet = Sets.newHashSet();
+		private final Set<QueryModelNode> spSet = Sets.newHashSet();
 		private int joinCount = 0;
 
 		public Set<QueryModelNode> getFilters() {
@@ -180,35 +179,35 @@ public class PCJOptimizerUtilities {
 		}
 
 		@Override
-		public void meet(Projection node) {
+		public void meet(final Projection node) {
 			node.getArg().visit(this);
 		}
 
 		@Override
-		public void meet(Filter node) {
+		public void meet(final Filter node) {
 			filterSet.add(node.getCondition());
 			node.getArg().visit(this);
 		}
 
 		@Override
-		public void meet(StatementPattern node) {
+		public void meet(final StatementPattern node) {
 			spSet.add(node);
 		}
 
 		@Override
-		public void meet(Join node) {
+		public void meet(final Join node) {
 			joinCount++;
 			super.meet(node);
 		}
 
 		@Override
-		public void meet(LeftJoin node) {
+		public void meet(final LeftJoin node) {
 			joinCount++;
 			super.meet(node);
 		}
 
 		@Override
-		public void meetNode(QueryModelNode node) {
+		public void meetNode(final QueryModelNode node) {
 			if (!(node instanceof Join || node instanceof LeftJoin
 					|| node instanceof StatementPattern || node instanceof Var
 					|| node instanceof Union || node instanceof Filter || node instanceof Projection)) {
@@ -238,18 +237,18 @@ public class PCJOptimizerUtilities {
 		protected Filter filter;
 		protected Set<String> filterVars;
 
-		public FilterRelocator(Filter filter) {
+		public FilterRelocator(final Filter filter) {
 			this.filter = filter;
 			filterVars = VarNameCollector.process(filter.getCondition());
 		}
 
-		public static void relocate(Filter filter) {
+		public static void relocate(final Filter filter) {
 			final FilterRelocator fr = new FilterRelocator(filter);
 			filter.visit(fr);
 		}
 
 		@Override
-		protected void meetNode(QueryModelNode node) {
+		protected void meetNode(final QueryModelNode node) {
 			// By default, do not traverse
 			assert node instanceof TupleExpr;
 
@@ -263,7 +262,7 @@ public class PCJOptimizerUtilities {
 		}
 
 		@Override
-		public void meet(Join join) {
+		public void meet(final Join join) {
 			if (join.getRightArg().getBindingNames().containsAll(filterVars)) {
 				// All required vars are bound by the left expr
 				join.getRightArg().visit(this);
@@ -277,12 +276,12 @@ public class PCJOptimizerUtilities {
 		}
 
 		@Override
-		public void meet(Filter node) {
+		public void meet(final Filter node) {
 			node.getArg().visit(this);
 		}
 
 		@Override
-		public void meet(LeftJoin leftJoin) {
+		public void meet(final LeftJoin leftJoin) {
 			if (leftJoin.getLeftArg().getBindingNames().containsAll(filterVars)) {
 				leftJoin.getLeftArg().visit(this);
 			} else {
@@ -291,7 +290,7 @@ public class PCJOptimizerUtilities {
 		}
 
 		@Override
-        public void meet(Union union) {
+        public void meet(final Union union) {
             boolean filterMoved = false;
             if (Sets.intersection(union.getRightArg().getBindingNames(), filterVars).size() > 0) {
                 relocate(filter, union.getRightArg());
@@ -300,7 +299,7 @@ public class PCJOptimizerUtilities {
  
             if (Sets.intersection(union.getLeftArg().getBindingNames(), filterVars).size() > 0) {
                 if (filterMoved) {
-                    Filter clone = new Filter(filter.getArg(), filter.getCondition().clone());
+                    final Filter clone = new Filter(filter.getArg(), filter.getCondition().clone());
                     relocate(clone, union.getLeftArg());
                 } else {
                     relocate(filter, union.getLeftArg());
@@ -309,36 +308,36 @@ public class PCJOptimizerUtilities {
         }
 
 		@Override
-		public void meet(Difference node) {
+		public void meet(final Difference node) {
 			if (Sets.intersection(node.getRightArg().getBindingNames(), filterVars).size() > 0) {
 				relocate(filter, node.getRightArg());
 			} else if (Sets.intersection(node.getLeftArg().getBindingNames(), filterVars).size() > 0) {
-				Filter clone = new Filter(filter.getArg(), filter
+				final Filter clone = new Filter(filter.getArg(), filter
 						.getCondition().clone());
 				relocate(clone, node.getLeftArg());
 			}
 		}
 
 		@Override
-		public void meet(Intersection node) {
+		public void meet(final Intersection node) {
 			if (Sets.intersection(node.getRightArg().getBindingNames(), filterVars).size() > 0) {
 				relocate(filter, node.getRightArg());
 			} else if (Sets.intersection(node.getLeftArg().getBindingNames(), filterVars).size() > 0) {
-				Filter clone = new Filter(filter.getArg(), filter
+				final Filter clone = new Filter(filter.getArg(), filter
 						.getCondition().clone());
 				relocate(clone, node.getLeftArg());
 			}
 		}
 
 		@Override
-		public void meet(EmptySet node) {
+		public void meet(final EmptySet node) {
 			if (filter.getParentNode() != null) {
 				// Remove filter from its original location
 				filter.replaceWith(filter.getArg());
 			}
 		}
 
-		protected void relocate(Filter filter, TupleExpr newFilterArg) {
+		protected void relocate(final Filter filter, final TupleExpr newFilterArg) {
 			if (!filter.getArg().equals(newFilterArg)) {
 				if (filter.getParentNode() != null) {
 					// Remove filter from its original location
@@ -351,10 +350,8 @@ public class PCJOptimizerUtilities {
 		}
 	}
 
-
-
-	public static boolean tupleContainsLeftJoins(TupleExpr node) {
-	    LeftJoinVisitor lj = new LeftJoinVisitor();
+	public static boolean tupleContainsLeftJoins(final TupleExpr node) {
+	    final LeftJoinVisitor lj = new LeftJoinVisitor();
 	    node.visit(lj);
         return lj.containsLeftJoin;
     }
@@ -368,18 +365,8 @@ public class PCJOptimizerUtilities {
         }
 
         @Override
-        public void meet(LeftJoin node) {
+        public void meet(final LeftJoin node) {
             containsLeftJoin = true;
         }
     }
-
-
-
-
-
-
-
-
-
-
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/provider/AbstractPcjIndexSetProvider.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/provider/AbstractPcjIndexSetProvider.java b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/provider/AbstractPcjIndexSetProvider.java
new file mode 100644
index 0000000..984153a
--- /dev/null
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/provider/AbstractPcjIndexSetProvider.java
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+package org.apache.rya.indexing.pcj.matching.provider;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.log4j.Logger;
+import org.apache.rya.api.instance.RyaDetails;
+import org.apache.rya.indexing.IndexPlanValidator.IndexedExecutionPlanGenerator;
+import org.apache.rya.indexing.IndexPlanValidator.ValidIndexCombinationGenerator;
+import org.apache.rya.indexing.external.matching.ExternalSetProvider;
+import org.apache.rya.indexing.external.matching.QuerySegment;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.pcj.matching.PCJOptimizerUtilities;
+import org.apache.rya.indexing.pcj.matching.PCJToSegmentConverter;
+import org.openrdf.query.algebra.TupleExpr;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Abstraction of {@link ExternalSetProvider} that provides {@link ExternalTupleSet}s.
+ * Implementations of this use either a user specified configuration information or user a specified
+ * List of ExternalTupleSets to populate an internal cache of ExternalTupleSets.  If a configuration
+ * is provided, the provider connects to an instance of RyaDetails and populates the cache with
+ * PCJs registered in RyaDetails.
+ */
+public abstract class AbstractPcjIndexSetProvider implements ExternalSetProvider<ExternalTupleSet> {
+    protected static final Logger log = Logger.getLogger(AbstractPcjIndexSetProvider.class);
+    protected static final PCJToSegmentConverter converter = new PCJToSegmentConverter();
+    protected List<ExternalTupleSet> indexCache;
+    protected final Configuration conf;
+    protected boolean init = false;
+
+    /**
+     * Creates a new {@link AbstractPcjIndexSetProvider} based on configuration only.
+     * @param conf - The {@link Configuration} used to connect to {@link RyaDetails}.
+     */
+    public AbstractPcjIndexSetProvider(final Configuration conf) {
+        this.conf = requireNonNull(conf);
+    }
+
+    /**
+     * Creates a new {@link AbstractPcjIndexSetProvider} based user provided {@link ExternalTupleSet}s.
+     * @param conf - The {@link Configuration} used to connect to {@link RyaDetails}.
+     * @param indices - The {@link ExternalTupleSet}s to populate the internal cache.
+     */
+    public AbstractPcjIndexSetProvider(final Configuration conf, final List<ExternalTupleSet> indices) {
+        requireNonNull(conf);
+        this.conf = conf;
+        indexCache = indices;
+        init = true;
+    }
+
+
+    /**
+     *
+     * @param indices
+     */
+    @VisibleForTesting
+    public void setIndices(final List<ExternalTupleSet> indices) {
+        indexCache = indices;
+        init = true;
+    }
+
+    /**
+     * @param segment - QuerySegment used to get relevant queries form index cache for matching
+     *
+     * @return Iterator of Lists (combos) of PCJs used to build an optimal query plan
+     */
+    @Override
+    public Iterator<List<ExternalTupleSet>> getExternalSetCombos(final QuerySegment<ExternalTupleSet> segment) {
+        final ValidIndexCombinationGenerator comboGen = new ValidIndexCombinationGenerator(segment.getOrderedNodes());
+        return comboGen.getValidIndexCombos(getExternalSets(segment));
+    }
+
+    /**
+     * @param segment - QuerySegment used to get relevant queries form index cache for matching
+     * @return List of PCJs for matching
+     */
+    @Override
+    public List<ExternalTupleSet> getExternalSets(final QuerySegment<ExternalTupleSet> segment) {
+        try {
+            if(!init) {
+                indexCache = PCJOptimizerUtilities.getValidPCJs(getIndices());
+                init = true;
+            }
+            final TupleExpr query = segment.getQuery().getTupleExpr();
+            final IndexedExecutionPlanGenerator iep = new IndexedExecutionPlanGenerator(query, indexCache);
+            final List<ExternalTupleSet> pcjs = iep.getNormalizedIndices();
+            final List<ExternalTupleSet> tuples = new ArrayList<>();
+            for (final ExternalTupleSet tuple: pcjs) {
+                final QuerySegment<ExternalTupleSet> pcj = converter.setToSegment(tuple);
+                if (segment.containsQuerySegment(pcj)) {
+                    tuples.add(tuple);
+                }
+            }
+            return tuples;
+
+        } catch (final Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * @return The size of the set index cache.
+     * @throws Exception
+     */
+    public int size() throws Exception {
+        if (!init) {
+            indexCache = PCJOptimizerUtilities.getValidPCJs(getIndices());
+            init = true;
+        }
+        return indexCache.size();
+    }
+
+    /**
+     * @param conf - client configuration
+     * @return - list of {@link ExternalTupleSet}s or PCJs that are either
+     *         specified by user in Configuration or exist in system.
+     *
+     * @throws Exception
+     */
+    protected abstract List<ExternalTupleSet> getIndices() throws PcjIndexSetException;
+
+    /**
+     * Exception thrown when failing to get the defined PCJS for a particular
+     * index.
+     */
+    public class PcjIndexSetException extends Exception {
+        public PcjIndexSetException(final String message) {
+            super(message);
+        }
+
+        public PcjIndexSetException(final String message, final Throwable cause) {
+            super(message, cause);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/provider/AccumuloIndexSetProvider.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/provider/AccumuloIndexSetProvider.java b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/provider/AccumuloIndexSetProvider.java
new file mode 100644
index 0000000..1fa3677
--- /dev/null
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/pcj/matching/provider/AccumuloIndexSetProvider.java
@@ -0,0 +1,139 @@
+/**
+ * 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.
+ */
+package org.apache.rya.indexing.pcj.matching.provider;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.log4j.Logger;
+import org.apache.rya.accumulo.instance.AccumuloRyaInstanceDetailsRepository;
+import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
+import org.apache.rya.api.instance.RyaDetailsRepository;
+import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException;
+import org.apache.rya.indexing.accumulo.ConfigUtils;
+import org.apache.rya.indexing.external.tupleSet.AccumuloIndexSet;
+import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException;
+import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjStorage;
+import org.apache.rya.indexing.pcj.storage.accumulo.PcjTableNameFactory;
+import org.apache.rya.indexing.pcj.storage.accumulo.PcjTables;
+import org.openrdf.query.MalformedQueryException;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.sail.SailException;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Implementation of {@link AbstractPcjIndexSetProvider} for Accumulo.
+ * This provider uses either user specified Accumulo configuration information or user a specified
+ * List of ExternalTupleSets to populate an internal cache of ExternalTupleSets.  If Accumulo configuration
+ * is provided, the provider connects to an instance of RyaDetails and populates the cache with
+ * PCJs registered in RyaDetails.
+ */
+public class AccumuloIndexSetProvider extends AbstractPcjIndexSetProvider {
+    private static final Logger log = Logger.getLogger(AccumuloIndexSetProvider.class);
+
+    public AccumuloIndexSetProvider(final Configuration conf) {
+        super(conf);
+    }
+
+    public AccumuloIndexSetProvider(final Configuration conf, final List<ExternalTupleSet> indices) {
+        super(conf, indices);
+    }
+
+    @Override
+    protected List<ExternalTupleSet> getIndices() throws PcjIndexSetException {
+        requireNonNull(conf);
+        try {
+            final String tablePrefix = requireNonNull(conf.get(RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX));
+            final Connector conn = requireNonNull(ConfigUtils.getConnector(conf));
+            List<String> tables = null;
+
+            if (conf instanceof RdfCloudTripleStoreConfiguration) {
+                tables = ((RdfCloudTripleStoreConfiguration) conf).getPcjTables();
+            }
+            // this maps associates pcj table name with pcj sparql query
+            final Map<String, String> indexTables = Maps.newLinkedHashMap();
+
+            try(final PrecomputedJoinStorage storage = new AccumuloPcjStorage(conn, tablePrefix)) {
+                final PcjTableNameFactory pcjFactory = new PcjTableNameFactory();
+
+                final boolean tablesProvided = tables != null && !tables.isEmpty();
+
+                if (tablesProvided) {
+                    // if tables provided, associate table name with sparql
+                    for (final String table : tables) {
+                        indexTables.put(table, storage.getPcjMetadata(pcjFactory.getPcjId(table)).getSparql());
+                    }
+                } else if (hasRyaDetails(tablePrefix, conn)) {
+                    // If this is a newer install of Rya, and it has PCJ Details, then
+                    // use those.
+                    final List<String> ids = storage.listPcjs();
+                    for (final String id : ids) {
+                        indexTables.put(pcjFactory.makeTableName(tablePrefix, id), storage.getPcjMetadata(id).getSparql());
+                    }
+                } else {
+                    // Otherwise figure it out by scanning tables.
+                    final PcjTables pcjTables = new PcjTables();
+                    for (final String table : conn.tableOperations().list()) {
+                        if (table.startsWith(tablePrefix + "INDEX")) {
+                            indexTables.put(table, pcjTables.getPcjMetadata(conn, table).getSparql());
+                        }
+                    }
+                }
+            }
+
+            // use table name sparql map (indexTables) to create {@link
+            // AccumuloIndexSet}
+            final List<ExternalTupleSet> index = Lists.newArrayList();
+            if (indexTables.isEmpty()) {
+                log.info("No Index found");
+            } else {
+                for (final String table : indexTables.keySet()) {
+                    final String indexSparqlString = indexTables.get(table);
+                    index.add(new AccumuloIndexSet(indexSparqlString, conf, table));
+                }
+            }
+
+            return index;
+        } catch (final PCJStorageException | AccumuloException | AccumuloSecurityException | MalformedQueryException
+                | SailException | QueryEvaluationException | TableNotFoundException e) {
+            throw new PcjIndexSetException("Failed to retrieve the indicies.", e);
+        }
+    }
+
+    private static boolean hasRyaDetails(final String ryaInstanceName, final Connector conn) {
+        final RyaDetailsRepository detailsRepo = new AccumuloRyaInstanceDetailsRepository(conn, ryaInstanceName);
+        try {
+            detailsRepo.getRyaInstanceDetails();
+            return true;
+        } catch (final RyaDetailsRepositoryException e) {
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java
index 5028454..78b4f52 100644
--- a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java
@@ -107,7 +107,7 @@ public class AccumuloBatchUpdatePCJIT extends AccumuloITBase {
             final String pcjId = pcjStorage.createPcj(sparql);
 
             // Run the test.
-            ryaClient.getBatchUpdatePCJ().get().batchUpdate(RYA_INSTANCE_NAME, pcjId);
+            ryaClient.getBatchUpdatePCJ().batchUpdate(RYA_INSTANCE_NAME, pcjId);
 
             // Verify the correct results were loaded into the PCJ table.
             final Set<BindingSet> expectedResults = new HashSet<>();

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloInstallIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloInstallIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloInstallIT.java
index da717d7..a8c7455 100644
--- a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloInstallIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloInstallIT.java
@@ -23,10 +23,9 @@ import static org.junit.Assert.assertTrue;
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.rya.accumulo.AccumuloITBase;
-import org.apache.rya.api.client.Install;
 import org.apache.rya.api.client.Install.DuplicateInstanceNameException;
 import org.apache.rya.api.client.Install.InstallConfiguration;
-import org.apache.rya.api.client.InstanceExists;
+import org.apache.rya.api.client.RyaClient;
 import org.apache.rya.api.client.RyaClientException;
 import org.apache.rya.api.instance.RyaDetailsRepository.NotInitializedException;
 import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException;
@@ -41,6 +40,14 @@ public class AccumuloInstallIT extends AccumuloITBase {
     public void install() throws AccumuloException, AccumuloSecurityException, DuplicateInstanceNameException, RyaClientException, NotInitializedException, RyaDetailsRepositoryException {
         // Install an instance of Rya.
         final String instanceName = getRyaInstanceName();
+        final AccumuloConnectionDetails connectionDetails = new AccumuloConnectionDetails(
+        		getUsername(),
+        		getPassword().toCharArray(),
+        		getInstanceName(),
+        		getZookeepers());
+
+        final RyaClient ryaClient = AccumuloRyaClientFactory.build(connectionDetails, getConnector());
+        
         final InstallConfiguration installConfig = InstallConfiguration.builder()
                 .setEnableTableHashPrefix(false)
                 .setEnableEntityCentricIndex(false)
@@ -48,39 +55,58 @@ public class AccumuloInstallIT extends AccumuloITBase {
                 .setEnableTemporalIndex(false)
                 .setEnablePcjIndex(false)
                 .setEnableGeoIndex(false)
-                .setFluoPcjAppName("fluo_app_name")
                 .build();
 
+
+        ryaClient.getInstall().install(instanceName, installConfig);
+
+        // Check that the instance exists.
+        assertTrue( ryaClient.getInstanceExists().exists(instanceName) );
+    }
+
+    @Test
+    public void install_withIndexers() throws AccumuloException, AccumuloSecurityException, DuplicateInstanceNameException, RyaClientException, NotInitializedException, RyaDetailsRepositoryException {
+        // Install an instance of Rya.
+        final String instanceName = getRyaInstanceName();
         final AccumuloConnectionDetails connectionDetails = new AccumuloConnectionDetails(
-                getUsername(),
-                getPassword().toCharArray(),
-                getInstanceName(),
-                getZookeepers());
+        		getUsername(),
+        		getPassword().toCharArray(),
+        		getInstanceName(),
+        		getZookeepers());
+
+        final RyaClient ryaClient = AccumuloRyaClientFactory.build(connectionDetails, getConnector());
+        
+        final InstallConfiguration installConfig = InstallConfiguration.builder()
+                .setEnableTableHashPrefix(true)
+                .setEnableEntityCentricIndex(true)
+                .setEnableFreeTextIndex(true)
+                .setEnableTemporalIndex(true)
+                .setEnablePcjIndex(true)
+                .setEnableGeoIndex(true)
+                .build();
 
-        final Install install = new AccumuloInstall(connectionDetails, getConnector());
-        install.install(instanceName, installConfig);
+        ryaClient.getInstall().install(instanceName, installConfig);
 
         // Check that the instance exists.
-        final InstanceExists instanceExists = new AccumuloInstanceExists(connectionDetails, getConnector());
-        assertTrue( instanceExists.exists(instanceName) );
+        assertTrue( ryaClient.getInstanceExists().exists(instanceName) );
     }
 
     @Test(expected = DuplicateInstanceNameException.class)
     public void install_alreadyExists() throws DuplicateInstanceNameException, RyaClientException, AccumuloException, AccumuloSecurityException {
         // Install an instance of Rya.
         final String instanceName = getRyaInstanceName();
-        final InstallConfiguration installConfig = InstallConfiguration.builder().build();
-
         final AccumuloConnectionDetails connectionDetails = new AccumuloConnectionDetails(
-                getUsername(),
-                getPassword().toCharArray(),
-                getInstanceName(),
-                getZookeepers());
+        		getUsername(),
+        		getPassword().toCharArray(),
+        		getInstanceName(),
+        		getZookeepers());
 
-        final Install install = new AccumuloInstall(connectionDetails, getConnector());
-        install.install(instanceName, installConfig);
+        final RyaClient ryaClient = AccumuloRyaClientFactory.build(connectionDetails, getConnector());
+        
+        final InstallConfiguration installConfig = InstallConfiguration.builder().build();
+        ryaClient.getInstall().install(instanceName, installConfig);
 
         // Install it again.
-        install.install(instanceName, installConfig);
+        ryaClient.getInstall().install(instanceName, installConfig);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloUninstallIT.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloUninstallIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloUninstallIT.java
index c4e4d54..e88e35c 100644
--- a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloUninstallIT.java
+++ b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloUninstallIT.java
@@ -22,11 +22,9 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import org.apache.rya.accumulo.AccumuloITBase;
-import org.apache.rya.api.client.Install;
 import org.apache.rya.api.client.Install.InstallConfiguration;
 import org.apache.rya.api.client.InstanceDoesNotExistException;
-import org.apache.rya.api.client.InstanceExists;
-import org.apache.rya.api.client.Uninstall;
+import org.apache.rya.api.client.RyaClient;
 import org.junit.Test;
 
 /**
@@ -62,20 +60,16 @@ public class AccumuloUninstallIT extends AccumuloITBase {
                 getPassword().toCharArray(),
                 getInstanceName(),
                 getZookeepers());
-
-        final Install install = new AccumuloInstall(connectionDetails, getConnector());
-        final String ryaInstanceName = getRyaInstanceName();
-        install.install(ryaInstanceName, installConfig);
+        final RyaClient ryaClient = AccumuloRyaClientFactory.build(connectionDetails, getConnector());
+        ryaClient.getInstall().install(getRyaInstanceName(), installConfig);
 
         // Check that the instance exists.
-        final InstanceExists instanceExists = new AccumuloInstanceExists(connectionDetails, getConnector());
-        assertTrue( instanceExists.exists(ryaInstanceName) );
+        assertTrue( ryaClient.getInstanceExists().exists(getRyaInstanceName()) );
 
         // Uninstall the instance of Rya.
-        final Uninstall uninstall = new AccumuloUninstall(connectionDetails, getConnector());
-        uninstall.uninstall(ryaInstanceName);
+        ryaClient.getUninstall().uninstall(getRyaInstanceName());
 
         // Verify that it no longer exists.
-        assertFalse( instanceExists.exists(ryaInstanceName) );
+        assertFalse( ryaClient.getInstanceExists().exists(getRyaInstanceName()) );
     }
 }
\ No newline at end of file


[8/8] incubator-rya git commit: RYA-303 Mongo PCJ Support. Closes #172.

Posted by ca...@apache.org.
RYA-303 Mongo PCJ Support. Closes #172.

Added implementation of MongoPcjStorage
Pcj serialization in mongo
added ITs for each interactor.
removed optional from RyaCommands create/delete/batch updated


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

Branch: refs/heads/master
Commit: c826ffea4a9046355ebae28c131042afba797918
Parents: 9f61101
Author: isper3at <sm...@gmail.com>
Authored: Fri May 12 16:40:44 2017 -0700
Committer: caleb <ca...@parsons.com>
Committed: Fri Jan 12 16:23:45 2018 -0500

----------------------------------------------------------------------
 .../rya/api/client/CreatePeriodicPCJ.java       |    8 +-
 .../org/apache/rya/api/client/RyaClient.java    |   19 +-
 .../rya/api/instance/ConfigurationFields.java   |    1 +
 .../api/instance/RyaDetailsToConfiguration.java |   28 +-
 .../rya/api/resolver/RyaToRdfConversions.java   |    6 +-
 .../rya/accumulo/RyaTestInstanceRule.java       |    7 +-
 .../apache/rya/mongodb/MongoDBQueryEngine.java  |    1 -
 .../mongodb/instance/MongoDetailsAdapter.java   |   44 +-
 .../org/apache/rya/mongodb/MongoITBase.java     |    2 +-
 .../instance/MongoDetailsAdapterTest.java       |    3 -
 .../instance/MongoRyaDetailsRepositoryIT.java   |  152 +-
 .../accumulo/AccumuloRyaClientFactory.java      |    6 +-
 .../api/client/mongo/MongoBatchUpdatePCJ.java   |  242 ++
 .../rya/api/client/mongo/MongoCreatePCJ.java    |   77 +
 .../rya/api/client/mongo/MongoDeletePCJ.java    |   68 +
 .../rya/api/client/mongo/MongoInstall.java      |   38 +-
 .../api/client/mongo/MongoRyaClientFactory.java |    6 +-
 .../rya/indexing/accumulo/ConfigUtils.java      |   20 +-
 .../rya/indexing/accumulo/ConfigUtils.java.orig |  529 -----
 .../external/PrecomputedJoinIndexerConfig.java  |    8 +-
 .../mongodb/pcj/MongoPcjIndexSetProvider.java   |  126 ++
 .../indexing/mongodb/pcj/MongoPcjQueryNode.java |  167 ++
 .../pcj/matching/AccumuloIndexSetProvider.java  |  221 --
 .../rya/indexing/pcj/matching/PCJOptimizer.java |   40 +-
 .../pcj/matching/PCJOptimizerUtilities.java     |   87 +-
 .../provider/AbstractPcjIndexSetProvider.java   |  159 ++
 .../provider/AccumuloIndexSetProvider.java      |  139 ++
 .../accumulo/AccumuloBatchUpdatePCJIT.java      |    2 +-
 .../api/client/accumulo/AccumuloInstallIT.java  |   66 +-
 .../client/accumulo/AccumuloUninstallIT.java    |   18 +-
 .../api/client/mongo/MongoBatchUpdatePCJIT.java |  148 ++
 .../rya/api/client/mongo/MongoCreatePCJIT.java  |  122 +
 .../rya/api/client/mongo/MongoDeletePCJIT.java  |   93 +
 .../client/mongo/MongoGetInstanceDetailsIT.java |   12 +-
 .../rya/api/client/mongo/MongoInstallIT.java    |   51 +-
 .../IndexPlanValidatorTest.java                 | 1453 ++++++------
 .../ThreshholdPlanSelectorTest.java             |    5 +-
 .../external/AccumuloConstantPcjIT.java         |    4 +-
 .../rya/indexing/external/AccumuloPcjIT.java    |   30 +-
 .../indexing/external/PCJOptionalTestIT.java    |   27 +-
 .../external/PcjIntegrationTestingUtil.java     |  168 +-
 .../external/PrecompJoinOptimizerIT.java        |   16 +-
 .../external/PrecompJoinOptimizerTest.java      |  792 +++----
 .../external/PrecompJoinOptimizerTest2.java     | 2121 +++++++++---------
 .../PrecompJoinOptimizerVarToConstTest.java     |   13 +-
 .../rya/indexing/mongo/MongoPCJIndexIT.java     |  233 ++
 .../indexing/mongo/MongoPcjIntegrationTest.java |  374 +++
 .../indexing/pcj/matching/PCJOptimizerTest.java |  314 +--
 .../periodic/KafkaLatencyBenchmark.java         |   10 +-
 .../benchmark/query/PCJOptimizerBenchmark.java  |   18 +-
 .../benchmark/query/QueryBenchmarkRunIT.java    |    2 +-
 extras/rya.indexing.pcj/pom.xml                 |   10 +
 .../storage/mongo/MongoBindingSetConverter.java |   56 +
 .../pcj/storage/mongo/MongoPcjDocuments.java    |  445 ++++
 .../pcj/storage/mongo/MongoPcjStorage.java      |  171 ++
 .../storage/mongo/MongoPcjDocumentsTest.java    |   91 +
 .../pcj/storage/mongo/MongoPcjStorageIT.java    |  348 +++
 .../mongo/PcjDocumentsIntegrationTest.java      |  460 ++++
 .../storage/mongo/PcjDocumentsWithMockTest.java |   98 +
 .../pcj/fluo/integration/CreateDeleteIT.java    |    2 +-
 .../indexing/pcj/fluo/integration/QueryIT.java  |   12 +-
 .../pcj/fluo/visibility/PcjVisibilityIT.java    |    2 +-
 .../pcj/fluo/test/base/KafkaExportITBase.java   |    2 +-
 .../pcj/functions/geo/GeoFunctionsIT.java       |    2 +-
 .../org/apache/rya/shell/RyaAdminCommands.java  |   49 +-
 .../apache/rya/shell/util/InstallPrompt.java    |   25 +-
 .../rya/shell/util/RyaDetailsFormatter.java     |   62 +-
 .../org/apache/rya/shell/MongoRyaShellIT.java   |   13 -
 .../apache/rya/shell/RyaAdminCommandsTest.java  |   94 +-
 .../rya/shell/util/RyaDetailsFormatterTest.java |    8 +-
 70 files changed, 6733 insertions(+), 3513 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/common/rya.api/src/main/java/org/apache/rya/api/client/CreatePeriodicPCJ.java
----------------------------------------------------------------------
diff --git a/common/rya.api/src/main/java/org/apache/rya/api/client/CreatePeriodicPCJ.java b/common/rya.api/src/main/java/org/apache/rya/api/client/CreatePeriodicPCJ.java
index 7c006d0..a046b6f 100644
--- a/common/rya.api/src/main/java/org/apache/rya/api/client/CreatePeriodicPCJ.java
+++ b/common/rya.api/src/main/java/org/apache/rya/api/client/CreatePeriodicPCJ.java
@@ -19,15 +19,15 @@
 package org.apache.rya.api.client;
 
 /**
- * This class creates new PeriodicPCJ for a given Rya instance.  
+ * This class creates new PeriodicPCJ for a given Rya instance.
  */
 public interface CreatePeriodicPCJ {
 
     /**
      * Creates a new PeriodicPCJ for a given Rya instance. The provided periodicTopic and bootStrapServers are used for
-     * registering new PeriodiNotifications with the underlying notification registration service. Typically, the
+     * registering new Periodic Notifications with the underlying notification registration service. Typically, the
      * bootStrapServers are the IP for the KafkaBrokers.
-     * 
+     *
      * @param instanceName - Rya instance to connect to
      * @param sparql - SPARQL query registered with the Periodic Service
      * @param periodicTopic - Kafka topic that new PeriodicNotifications are exported to for registration with the
@@ -36,5 +36,5 @@ public interface CreatePeriodicPCJ {
      * @return Fluo Query Id of the registered Periodic Query
      */
     public String createPeriodicPCJ(String instanceName, String sparql, String periodicTopic, String bootStrapServers) throws RyaClientException;
-    
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/common/rya.api/src/main/java/org/apache/rya/api/client/RyaClient.java
----------------------------------------------------------------------
diff --git a/common/rya.api/src/main/java/org/apache/rya/api/client/RyaClient.java b/common/rya.api/src/main/java/org/apache/rya/api/client/RyaClient.java
index a14e300..92b18a1 100644
--- a/common/rya.api/src/main/java/org/apache/rya/api/client/RyaClient.java
+++ b/common/rya.api/src/main/java/org/apache/rya/api/client/RyaClient.java
@@ -34,12 +34,12 @@ import net.jcip.annotations.Immutable;
 public class RyaClient {
     // Administrative functions.
     private final Install install;
-    private final Optional<CreatePCJ> createPcj;
-    private final Optional<DeletePCJ> deletePcj;
+    private final CreatePCJ createPcj;
+    private final DeletePCJ deletePcj;
     private final Optional<CreatePeriodicPCJ> createPeriodicPcj;
     private final Optional<DeletePeriodicPCJ> deletePeriodicPcj;
     private final Optional<ListIncrementalQueries> listIncrementalQueries;
-    private final Optional<BatchUpdatePCJ> bactchUpdatePCJ;
+    private final BatchUpdatePCJ bactchUpdatePCJ;
     private final GetInstanceDetails getInstanceDetails;
     private final InstanceExists instanceExists;
     private final ListInstances listInstances;
@@ -55,12 +55,11 @@ public class RyaClient {
      */
     public RyaClient(
             final Install install,
-            final Optional<CreatePCJ> createPcj,
-            final Optional<DeletePCJ> deletePcj,
+            final CreatePCJ createPcj, final DeletePCJ deletePcj,
             final Optional<CreatePeriodicPCJ> createPeriodicPcj,
             final Optional<DeletePeriodicPCJ> deletePeriodicPcj,
             final Optional<ListIncrementalQueries> listIncrementalQueries,
-            final Optional<BatchUpdatePCJ> batchUpdatePcj,
+            final BatchUpdatePCJ batchUpdatePcj,
             final GetInstanceDetails getInstanceDetails,
             final InstanceExists instanceExists,
             final ListInstances listInstances,
@@ -76,7 +75,7 @@ public class RyaClient {
         this.createPeriodicPcj = requireNonNull(createPeriodicPcj);
         this.deletePeriodicPcj = requireNonNull(deletePeriodicPcj);
         this.listIncrementalQueries = requireNonNull(listIncrementalQueries);
-        this.bactchUpdatePCJ = requireNonNull(batchUpdatePcj);
+        bactchUpdatePCJ = requireNonNull(batchUpdatePcj);
         this.getInstanceDetails = requireNonNull(getInstanceDetails);
         this.instanceExists = requireNonNull(instanceExists);
         this.listInstances = requireNonNull(listInstances);
@@ -99,7 +98,7 @@ public class RyaClient {
      * @return An instance of {@link CreatePCJ} that is connected to a Rya storage
      *   if the Rya instance supports PCJ indexing.
      */
-    public Optional<CreatePCJ> getCreatePCJ() {
+    public CreatePCJ getCreatePCJ() {
         return createPcj;
     }
 
@@ -107,7 +106,7 @@ public class RyaClient {
      * @return An instance of {@link DeletePCJ} that is connected to a Rya storage
      *   if the Rya instance supports PCJ indexing.
      */
-    public Optional<DeletePCJ> getDeletePCJ() {
+    public DeletePCJ getDeletePCJ() {
         return deletePcj;
     }
 
@@ -137,7 +136,7 @@ public class RyaClient {
      * @return An instance of {@link BatchUpdatePCJ} that is connect to a Rya storage
      *   if the Rya instance supports PCJ indexing.
      */
-    public Optional<BatchUpdatePCJ> getBatchUpdatePCJ() {
+    public BatchUpdatePCJ getBatchUpdatePCJ() {
         return bactchUpdatePCJ;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/common/rya.api/src/main/java/org/apache/rya/api/instance/ConfigurationFields.java
----------------------------------------------------------------------
diff --git a/common/rya.api/src/main/java/org/apache/rya/api/instance/ConfigurationFields.java b/common/rya.api/src/main/java/org/apache/rya/api/instance/ConfigurationFields.java
index 086c3fb..4173dd3 100644
--- a/common/rya.api/src/main/java/org/apache/rya/api/instance/ConfigurationFields.java
+++ b/common/rya.api/src/main/java/org/apache/rya/api/instance/ConfigurationFields.java
@@ -32,6 +32,7 @@ class ConfigurationFields {
     static final String USE_TEMPORAL = "sc.use_temporal";
     static final String USE_ENTITY = "sc.use_entity";
     static final String USE_PCJ_UPDATER = "sc.use.updater";
+    static final String USE_MONGO = "sc.useMongo";
     static final String FLUO_APP_NAME = "rya.indexing.pcj.fluo.fluoAppName";
     static final String PCJ_UPDATER_TYPE = "rya.indexing.pcj.updaterType";
     static final String PCJ_STORAGE_TYPE = "rya.indexing.pcj.storageType";

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/common/rya.api/src/main/java/org/apache/rya/api/instance/RyaDetailsToConfiguration.java
----------------------------------------------------------------------
diff --git a/common/rya.api/src/main/java/org/apache/rya/api/instance/RyaDetailsToConfiguration.java b/common/rya.api/src/main/java/org/apache/rya/api/instance/RyaDetailsToConfiguration.java
index 2605906..a8d47ba 100644
--- a/common/rya.api/src/main/java/org/apache/rya/api/instance/RyaDetailsToConfiguration.java
+++ b/common/rya.api/src/main/java/org/apache/rya/api/instance/RyaDetailsToConfiguration.java
@@ -51,17 +51,29 @@ public class RyaDetailsToConfiguration {
 
         checkAndSet(conf, ConfigurationFields.USE_ENTITY, details.getEntityCentricIndexDetails().isEnabled());
         checkAndSet(conf, ConfigurationFields.USE_FREETEXT, details.getFreeTextIndexDetails().isEnabled());
-      //RYA-215        checkAndSet(conf, ConfigurationFields.USE_GEO, details.getGeoIndexDetails().isEnabled());
+        //RYA-215        checkAndSet(conf, ConfigurationFields.USE_GEO, details.getGeoIndexDetails().isEnabled());
         checkAndSet(conf, ConfigurationFields.USE_TEMPORAL, details.getTemporalIndexDetails().isEnabled());
         final PCJIndexDetails pcjDetails = details.getPCJIndexDetails();
-        if (pcjDetails.isEnabled() && pcjDetails.getFluoDetails().isPresent()) {
-            checkAndSet(conf, ConfigurationFields.USE_PCJ_UPDATER, true);
-            conf.set(ConfigurationFields.FLUO_APP_NAME, pcjDetails.getFluoDetails().get().getUpdateAppName());
-            conf.set(ConfigurationFields.PCJ_UPDATER_TYPE, "FLUO");
-            conf.set(ConfigurationFields.PCJ_STORAGE_TYPE, "ACCUMULO");
+        
+        if(conf.getBoolean(ConfigurationFields.USE_MONGO, false) ) {
+        	if(pcjDetails.isEnabled()) {
+        		conf.set(ConfigurationFields.PCJ_STORAGE_TYPE, "MONGO");
+        		//mongo does not currently support pcj updaters
+        		checkAndSet(conf, ConfigurationFields.USE_PCJ_UPDATER, false);
+        		conf.set(ConfigurationFields.PCJ_UPDATER_TYPE, "NO_UPDATE");
+        	}
         } else {
-            checkAndSet(conf, ConfigurationFields.USE_PCJ_UPDATER, false);
-            conf.set(ConfigurationFields.PCJ_UPDATER_TYPE, "NO_UPDATE");
+        	if (pcjDetails.isEnabled() ) {
+        		conf.set(ConfigurationFields.PCJ_STORAGE_TYPE, "ACCUMULO");
+        		if (pcjDetails.getFluoDetails().isPresent()) {
+        			checkAndSet(conf, ConfigurationFields.USE_PCJ_UPDATER, true);
+        			conf.set(ConfigurationFields.FLUO_APP_NAME, pcjDetails.getFluoDetails().get().getUpdateAppName());
+        			conf.set(ConfigurationFields.PCJ_UPDATER_TYPE, "FLUO");
+        		} else {
+        			checkAndSet(conf, ConfigurationFields.USE_PCJ_UPDATER, false);
+        			conf.set(ConfigurationFields.PCJ_UPDATER_TYPE, "NO_UPDATE");
+        		}
+        	}
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/common/rya.api/src/main/java/org/apache/rya/api/resolver/RyaToRdfConversions.java
----------------------------------------------------------------------
diff --git a/common/rya.api/src/main/java/org/apache/rya/api/resolver/RyaToRdfConversions.java b/common/rya.api/src/main/java/org/apache/rya/api/resolver/RyaToRdfConversions.java
index a59ba23..51062c9 100644
--- a/common/rya.api/src/main/java/org/apache/rya/api/resolver/RyaToRdfConversions.java
+++ b/common/rya.api/src/main/java/org/apache/rya/api/resolver/RyaToRdfConversions.java
@@ -43,6 +43,10 @@ public class RyaToRdfConversions {
     public static URI convertURI(RyaURI uri) {
         return new URIImpl(uri.getData());
     }
+    
+    private static URI convertURI(RyaType value) {
+        return new URIImpl(value.getData());
+    }
 
     public static Literal convertLiteral(RyaType literal) {
         if (XMLSchema.STRING.equals(literal.getDataType())) {
@@ -55,7 +59,7 @@ public class RyaToRdfConversions {
 
     public static Value convertValue(RyaType value) {
         //assuming either uri or Literal here
-        return (value instanceof RyaURI) ? convertURI((RyaURI) value) : convertLiteral(value);
+        return (value instanceof RyaURI || value.getDataType().equals(XMLSchema.ANYURI)) ? convertURI(value) : convertLiteral(value);
     }
 
     public static Statement convertStatement(RyaStatement statement) {

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/dao/accumulo.rya/src/test/java/org/apache/rya/accumulo/RyaTestInstanceRule.java
----------------------------------------------------------------------
diff --git a/dao/accumulo.rya/src/test/java/org/apache/rya/accumulo/RyaTestInstanceRule.java b/dao/accumulo.rya/src/test/java/org/apache/rya/accumulo/RyaTestInstanceRule.java
index 38b4b43..3bbceb9 100644
--- a/dao/accumulo.rya/src/test/java/org/apache/rya/accumulo/RyaTestInstanceRule.java
+++ b/dao/accumulo.rya/src/test/java/org/apache/rya/accumulo/RyaTestInstanceRule.java
@@ -1,9 +1,8 @@
 package org.apache.rya.accumulo;
 
-import com.google.common.base.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+
 import org.apache.rya.accumulo.instance.AccumuloRyaInstanceDetailsRepository;
-import org.apache.rya.api.client.Install.InstallConfiguration;
-import org.apache.rya.api.client.RyaClient;
 import org.apache.rya.api.instance.RyaDetails;
 import org.apache.rya.api.instance.RyaDetails.EntityCentricIndexDetails;
 import org.apache.rya.api.instance.RyaDetails.FreeTextIndexDetails;
@@ -14,7 +13,7 @@ import org.apache.rya.api.instance.RyaDetails.TemporalIndexDetails;
 import org.apache.rya.api.instance.RyaDetailsRepository;
 import org.junit.rules.ExternalResource;
 
-import java.util.concurrent.atomic.AtomicInteger;
+import com.google.common.base.Optional;
 
 /**
  * Licensed to the Apache Software Foundation (ASF) under one

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java
----------------------------------------------------------------------
diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java
index e01fa34..9ddb15a 100644
--- a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java
+++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java
@@ -154,6 +154,5 @@ public class MongoDBQueryEngine implements RyaQueryEngine<StatefulMongoDBRdfConf
 
     @Override
     public void close() throws IOException {
-//        if (mongoClient != null){ mongoClient.close(); }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/instance/MongoDetailsAdapter.java
----------------------------------------------------------------------
diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/instance/MongoDetailsAdapter.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/instance/MongoDetailsAdapter.java
index 3b77a88..8010808 100644
--- a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/instance/MongoDetailsAdapter.java
+++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/instance/MongoDetailsAdapter.java
@@ -29,7 +29,6 @@ import org.apache.rya.api.instance.RyaDetails.EntityCentricIndexDetails;
 import org.apache.rya.api.instance.RyaDetails.FreeTextIndexDetails;
 import org.apache.rya.api.instance.RyaDetails.JoinSelectivityDetails;
 import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails;
-import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.FluoDetails;
 import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.PCJDetails;
 import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.PCJDetails.PCJUpdateStrategy;
 import org.apache.rya.api.instance.RyaDetails.ProspectorDetails;
@@ -100,13 +99,13 @@ public class MongoDetailsAdapter {
     public static BasicDBObject toDBObject(final RyaDetails details) {
         Preconditions.checkNotNull(details);
         final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start()
-            .add(INSTANCE_KEY, details.getRyaInstanceName())
-            .add(VERSION_KEY, details.getRyaVersion())
-            .add(ENTITY_DETAILS_KEY, details.getEntityCentricIndexDetails().isEnabled())
-          //RYA-215            .add(GEO_DETAILS_KEY, details.getGeoIndexDetails().isEnabled())
-            .add(PCJ_DETAILS_KEY, toDBObject(details.getPCJIndexDetails()))
-            .add(TEMPORAL_DETAILS_KEY, details.getTemporalIndexDetails().isEnabled())
-            .add(FREETEXT_DETAILS_KEY, details.getFreeTextIndexDetails().isEnabled());
+                .add(INSTANCE_KEY, details.getRyaInstanceName())
+                .add(VERSION_KEY, details.getRyaVersion())
+                .add(ENTITY_DETAILS_KEY, details.getEntityCentricIndexDetails().isEnabled())
+                //RYA-215            .add(GEO_DETAILS_KEY, details.getGeoIndexDetails().isEnabled())
+                .add(PCJ_DETAILS_KEY, toDBObject(details.getPCJIndexDetails()))
+                .add(TEMPORAL_DETAILS_KEY, details.getTemporalIndexDetails().isEnabled())
+                .add(FREETEXT_DETAILS_KEY, details.getFreeTextIndexDetails().isEnabled());
         if(details.getProspectorDetails().getLastUpdated().isPresent()) {
             builder.add(PROSPECTOR_DETAILS_KEY, details.getProspectorDetails().getLastUpdated().get());
         }
@@ -124,11 +123,6 @@ public class MongoDetailsAdapter {
         // Is Enabled
         builder.add(PCJ_ENABLED_KEY, pcjIndexDetails.isEnabled());
 
-        // Fluo Details if present.
-        if(pcjIndexDetails.getFluoDetails().isPresent()) {
-            builder.add(PCJ_FLUO_KEY, pcjIndexDetails.getFluoDetails().get().getUpdateAppName());
-        }
-
         // Add the PCJDetail objects.
         final List<DBObject> pcjDetailsList = new ArrayList<>();
         for(final PCJDetails pcjDetails : pcjIndexDetails.getPCJDetails().values()) {
@@ -163,17 +157,17 @@ public class MongoDetailsAdapter {
     public static RyaDetails toRyaDetails(final DBObject mongoObj) throws MalformedRyaDetailsException {
         final BasicDBObject basicObj = (BasicDBObject) mongoObj;
         try {
-        return RyaDetails.builder()
-            .setRyaInstanceName(basicObj.getString(INSTANCE_KEY))
-            .setRyaVersion(basicObj.getString(VERSION_KEY))
-            .setEntityCentricIndexDetails(new EntityCentricIndexDetails(basicObj.getBoolean(ENTITY_DETAILS_KEY)))
-          //RYA-215            .setGeoIndexDetails(new GeoIndexDetails(basicObj.getBoolean(GEO_DETAILS_KEY)))
-            .setPCJIndexDetails(getPCJIndexDetails(basicObj))
-            .setTemporalIndexDetails(new TemporalIndexDetails(basicObj.getBoolean(TEMPORAL_DETAILS_KEY)))
-            .setFreeTextDetails(new FreeTextIndexDetails(basicObj.getBoolean(FREETEXT_DETAILS_KEY)))
-            .setProspectorDetails(new ProspectorDetails(Optional.<Date>fromNullable(basicObj.getDate(PROSPECTOR_DETAILS_KEY))))
-            .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.<Date>fromNullable(basicObj.getDate(JOIN_SELECTIVITY_DETAILS_KEY))))
-            .build();
+            return RyaDetails.builder()
+                    .setRyaInstanceName(basicObj.getString(INSTANCE_KEY))
+                    .setRyaVersion(basicObj.getString(VERSION_KEY))
+                    .setEntityCentricIndexDetails(new EntityCentricIndexDetails(basicObj.getBoolean(ENTITY_DETAILS_KEY)))
+                    //RYA-215            .setGeoIndexDetails(new GeoIndexDetails(basicObj.getBoolean(GEO_DETAILS_KEY)))
+                    .setPCJIndexDetails(getPCJIndexDetails(basicObj))
+                    .setTemporalIndexDetails(new TemporalIndexDetails(basicObj.getBoolean(TEMPORAL_DETAILS_KEY)))
+                    .setFreeTextDetails(new FreeTextIndexDetails(basicObj.getBoolean(FREETEXT_DETAILS_KEY)))
+                    .setProspectorDetails(new ProspectorDetails(Optional.<Date>fromNullable(basicObj.getDate(PROSPECTOR_DETAILS_KEY))))
+                    .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.<Date>fromNullable(basicObj.getDate(JOIN_SELECTIVITY_DETAILS_KEY))))
+                    .build();
         } catch(final Exception e) {
             throw new MalformedRyaDetailsException("Failed to make RyaDetail from Mongo Object, it is malformed.", e);
         }
@@ -186,7 +180,7 @@ public class MongoDetailsAdapter {
         if (!pcjIndexDBO.getBoolean(PCJ_ENABLED_KEY)) {
             pcjBuilder.setEnabled(false);
         } else {
-            pcjBuilder.setEnabled(true).setFluoDetails(new FluoDetails(pcjIndexDBO.getString(PCJ_FLUO_KEY)));
+            pcjBuilder.setEnabled(true);//no fluo details to set since mongo has no fluo support
             final BasicDBList pcjs = (BasicDBList) pcjIndexDBO.get(PCJ_PCJS_KEY);
             if (pcjs != null) {
                 for (int ii = 0; ii < pcjs.size(); ii++) {

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/MongoITBase.java
----------------------------------------------------------------------
diff --git a/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/MongoITBase.java b/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/MongoITBase.java
index 1aaf6c2..bd3870f 100644
--- a/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/MongoITBase.java
+++ b/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/MongoITBase.java
@@ -43,7 +43,7 @@ public class MongoITBase {
         final MongoDBRdfConfiguration conf = new MongoDBRdfConfiguration( new Configuration() );
         conf.setBoolean("sc.useMongo", true);
         conf.setTablePrefix("test_");
-        conf.setMongoDBName("testDB");
+        conf.setMongoDBName(conf.getRyaInstanceName());
         conf.setMongoHostname(EmbeddedMongoSingleton.getMongodConfig().net().getServerAddress().getHostAddress());
         conf.setMongoPort(Integer.toString(EmbeddedMongoSingleton.getMongodConfig().net().getPort()));
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoDetailsAdapterTest.java
----------------------------------------------------------------------
diff --git a/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoDetailsAdapterTest.java b/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoDetailsAdapterTest.java
index 875f4e5..0ea9456 100644
--- a/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoDetailsAdapterTest.java
+++ b/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoDetailsAdapterTest.java
@@ -85,7 +85,6 @@ public class MongoDetailsAdapterTest {
                         //RYA-215            + "geoDetails : true,"
                         + "pcjDetails : {"
                         +    "enabled : true ,"
-                        +    "fluoName : \"fluo\","
                         +    "pcjs : [ "
                         +       "{"
                         +          "id : \"pcj_0\","
@@ -150,7 +149,6 @@ public class MongoDetailsAdapterTest {
                 .setPCJIndexDetails(
                         PCJIndexDetails.builder()
                         .setEnabled(true)
-                        .setFluoDetails(new FluoDetails("fluo"))
                         .addPCJDetails(
                                 PCJDetails.builder()
                                 .setId("pcj_0")
@@ -242,7 +240,6 @@ public class MongoDetailsAdapterTest {
                         //RYA-215                + "geoDetails : false,"
                         + "pcjDetails : {"
                         +    "enabled : true,"
-                        +    "fluoName : \"fluo\","
                         +    "pcjs : [ ]"
                         + "},"
                         + "temporalDetails : false,"

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoRyaDetailsRepositoryIT.java
----------------------------------------------------------------------
diff --git a/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoRyaDetailsRepositoryIT.java b/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoRyaDetailsRepositoryIT.java
index dd5088e..5321db5 100644
--- a/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoRyaDetailsRepositoryIT.java
+++ b/dao/mongodb.rya/src/test/java/org/apache/rya/mongodb/instance/MongoRyaDetailsRepositoryIT.java
@@ -64,27 +64,26 @@ public class MongoRyaDetailsRepositoryIT extends MongoITBase {
 
         // Create the metadata object the repository will be initialized with.
         final RyaDetails details = RyaDetails.builder()
-            .setRyaInstanceName(instanceName)
-            .setRyaVersion("1.2.3.4")
-            .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
-          //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
-            .setTemporalIndexDetails( new TemporalIndexDetails(true) )
-            .setFreeTextDetails( new FreeTextIndexDetails(true) )
-            .setPCJIndexDetails(
-                    PCJIndexDetails.builder()
+                .setRyaInstanceName(instanceName)
+                .setRyaVersion("1.2.3.4")
+                .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
+                //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
+                .setTemporalIndexDetails( new TemporalIndexDetails(true) )
+                .setFreeTextDetails( new FreeTextIndexDetails(true) )
+                .setPCJIndexDetails(
+                        PCJIndexDetails.builder()
                         .setEnabled(true)
-                        .setFluoDetails( new FluoDetails("test_instance_rya_pcj_updater") )
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 1")
-                                    .setUpdateStrategy(PCJUpdateStrategy.BATCH)
-                                    .setLastUpdateTime( new Date() ))
+                                .setId("pcj 1")
+                                .setUpdateStrategy(PCJUpdateStrategy.BATCH)
+                                .setLastUpdateTime( new Date() ))
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 2")))
-            .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
-            .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
-            .build();
+                                .setId("pcj 2")))
+                .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
+                .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
+                .build();
 
         // Setup the repository that will be tested using a mock instance of MongoDB.
         final RyaDetailsRepository repo = new MongoRyaInstanceDetailsRepository(client, instanceName);
@@ -105,27 +104,27 @@ public class MongoRyaDetailsRepositoryIT extends MongoITBase {
 
         // Create the metadata object the repository will be initialized with.
         final RyaDetails details = RyaDetails.builder()
-            .setRyaInstanceName(instanceName)
-            .setRyaVersion("1.2.3.4")
-            .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
-          //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
-            .setTemporalIndexDetails( new TemporalIndexDetails(true) )
-            .setFreeTextDetails( new FreeTextIndexDetails(true) )
-            .setPCJIndexDetails(
-                    PCJIndexDetails.builder()
+                .setRyaInstanceName(instanceName)
+                .setRyaVersion("1.2.3.4")
+                .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
+                //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
+                .setTemporalIndexDetails( new TemporalIndexDetails(true) )
+                .setFreeTextDetails( new FreeTextIndexDetails(true) )
+                .setPCJIndexDetails(
+                        PCJIndexDetails.builder()
                         .setEnabled(true)
                         .setFluoDetails( new FluoDetails("test_instance_rya_pcj_updater") )
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 1")
-                                    .setUpdateStrategy(PCJUpdateStrategy.BATCH)
-                                    .setLastUpdateTime( new Date() ))
+                                .setId("pcj 1")
+                                .setUpdateStrategy(PCJUpdateStrategy.BATCH)
+                                .setLastUpdateTime( new Date() ))
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 2")))
-            .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
-            .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
-            .build();
+                                .setId("pcj 2")))
+                .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
+                .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
+                .build();
 
         // Setup the repository that will be tested using a mock instance of MongoDB.
         final RyaDetailsRepository repo = new MongoRyaInstanceDetailsRepository(client, instanceName);
@@ -152,27 +151,27 @@ public class MongoRyaDetailsRepositoryIT extends MongoITBase {
 
         // Create the metadata object the repository will be initialized with.
         final RyaDetails details = RyaDetails.builder()
-            .setRyaInstanceName(instanceName)
-            .setRyaVersion("1.2.3.4")
-            .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
-          //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
-            .setTemporalIndexDetails( new TemporalIndexDetails(true) )
-            .setFreeTextDetails( new FreeTextIndexDetails(true) )
-            .setPCJIndexDetails(
-                    PCJIndexDetails.builder()
+                .setRyaInstanceName(instanceName)
+                .setRyaVersion("1.2.3.4")
+                .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
+                //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
+                .setTemporalIndexDetails( new TemporalIndexDetails(true) )
+                .setFreeTextDetails( new FreeTextIndexDetails(true) )
+                .setPCJIndexDetails(
+                        PCJIndexDetails.builder()
                         .setEnabled(true)
                         .setFluoDetails( new FluoDetails("test_instance_rya_pcj_updater") )
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 1")
-                                    .setUpdateStrategy(PCJUpdateStrategy.BATCH)
-                                    .setLastUpdateTime( new Date() ))
+                                .setId("pcj 1")
+                                .setUpdateStrategy(PCJUpdateStrategy.BATCH)
+                                .setLastUpdateTime( new Date() ))
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 2")))
-            .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
-            .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
-            .build();
+                                .setId("pcj 2")))
+                .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
+                .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
+                .build();
 
         // Setup the repository that will be tested using a mock instance of MongoDB.
         final RyaDetailsRepository repo = new MongoRyaInstanceDetailsRepository(client, "testInstance");
@@ -199,27 +198,26 @@ public class MongoRyaDetailsRepositoryIT extends MongoITBase {
 
         // Create the metadata object the repository will be initialized with.
         final RyaDetails details = RyaDetails.builder()
-            .setRyaInstanceName(instanceName)
-            .setRyaVersion("1.2.3.4")
-            .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
-          //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
-            .setTemporalIndexDetails( new TemporalIndexDetails(true) )
-            .setFreeTextDetails( new FreeTextIndexDetails(true) )
-            .setPCJIndexDetails(
-                    PCJIndexDetails.builder()
+                .setRyaInstanceName(instanceName)
+                .setRyaVersion("1.2.3.4")
+                .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
+                //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
+                .setTemporalIndexDetails( new TemporalIndexDetails(true) )
+                .setFreeTextDetails( new FreeTextIndexDetails(true) )
+                .setPCJIndexDetails(
+                        PCJIndexDetails.builder()
                         .setEnabled(true)
-                        .setFluoDetails( new FluoDetails("test_instance_rya_pcj_updater") )
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 1")
-                                    .setUpdateStrategy(PCJUpdateStrategy.BATCH)
-                                    .setLastUpdateTime( new Date() ))
+                                .setId("pcj 1")
+                                .setUpdateStrategy(PCJUpdateStrategy.BATCH)
+                                .setLastUpdateTime( new Date() ))
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 2")))
-            .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
-            .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
-            .build();
+                                .setId("pcj 2")))
+                .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
+                .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
+                .build();
 
         // Setup the repository that will be tested using a mock instance of MongoDB.
         final RyaDetailsRepository repo = new MongoRyaInstanceDetailsRepository(client, "testInstance");
@@ -246,27 +244,27 @@ public class MongoRyaDetailsRepositoryIT extends MongoITBase {
 
         // Create the metadata object the repository will be initialized with.
         final RyaDetails details = RyaDetails.builder()
-            .setRyaInstanceName(instanceName)
-            .setRyaVersion("1.2.3.4")
-            .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
-          //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
-            .setTemporalIndexDetails( new TemporalIndexDetails(true) )
-            .setFreeTextDetails( new FreeTextIndexDetails(true) )
-            .setPCJIndexDetails(
-                    PCJIndexDetails.builder()
+                .setRyaInstanceName(instanceName)
+                .setRyaVersion("1.2.3.4")
+                .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) )
+                //RYA-215            .setGeoIndexDetails( new GeoIndexDetails(true) )
+                .setTemporalIndexDetails( new TemporalIndexDetails(true) )
+                .setFreeTextDetails( new FreeTextIndexDetails(true) )
+                .setPCJIndexDetails(
+                        PCJIndexDetails.builder()
                         .setEnabled(true)
                         .setFluoDetails( new FluoDetails("test_instance_rya_pcj_updater") )
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 1")
-                                    .setUpdateStrategy(PCJUpdateStrategy.BATCH)
-                                    .setLastUpdateTime( new Date() ))
+                                .setId("pcj 1")
+                                .setUpdateStrategy(PCJUpdateStrategy.BATCH)
+                                .setLastUpdateTime( new Date() ))
                         .addPCJDetails(
                                 PCJDetails.builder()
-                                    .setId("pcj 2")))
-            .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
-            .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
-            .build();
+                                .setId("pcj 2")))
+                .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) )
+                .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) )
+                .build();
 
         // Setup the repository that will be tested using a mock instance of MongoDB.
         final RyaDetailsRepository repo = new MongoRyaInstanceDetailsRepository(client, "testInstance");

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java b/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java
index f9df491..17fddaa 100644
--- a/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java
+++ b/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java
@@ -52,12 +52,12 @@ public class AccumuloRyaClientFactory {
         // Build the RyaCommands option with the initialized commands.
         return new RyaClient(
                 new AccumuloInstall(connectionDetails, connector),
-                Optional.of(new AccumuloCreatePCJ(connectionDetails, connector)),
-                Optional.of(new AccumuloDeletePCJ(connectionDetails, connector)),
+                new AccumuloCreatePCJ(connectionDetails, connector),
+                new AccumuloDeletePCJ(connectionDetails, connector),
                 Optional.of(new AccumuloCreatePeriodicPCJ(connectionDetails, connector)),
                 Optional.of(new AccumuloDeletePeriodicPCJ(connectionDetails, connector)),
                 Optional.of(new AccumuloListIncrementalQueries(connectionDetails, connector)),
-                Optional.of(new AccumuloBatchUpdatePCJ(connectionDetails, connector)),
+                new AccumuloBatchUpdatePCJ(connectionDetails, connector),
                 new AccumuloGetInstanceDetails(connectionDetails, connector),
                 new AccumuloInstanceExists(connectionDetails, connector),
                 new AccumuloListInstances(connectionDetails, connector),

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoBatchUpdatePCJ.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoBatchUpdatePCJ.java b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoBatchUpdatePCJ.java
new file mode 100644
index 0000000..3fe99ef
--- /dev/null
+++ b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoBatchUpdatePCJ.java
@@ -0,0 +1,242 @@
+/**
+ * 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.
+ */
+package org.apache.rya.api.client.mongo;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.rya.api.client.BatchUpdatePCJ;
+import org.apache.rya.api.client.InstanceDoesNotExistException;
+import org.apache.rya.api.client.InstanceExists;
+import org.apache.rya.api.client.PCJDoesNotExistException;
+import org.apache.rya.api.client.RyaClientException;
+import org.apache.rya.api.instance.RyaDetails;
+import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.PCJDetails;
+import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.PCJDetails.PCJUpdateStrategy;
+import org.apache.rya.api.instance.RyaDetailsRepository;
+import org.apache.rya.api.instance.RyaDetailsRepository.NotInitializedException;
+import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException;
+import org.apache.rya.api.instance.RyaDetailsUpdater;
+import org.apache.rya.api.instance.RyaDetailsUpdater.RyaDetailsMutator;
+import org.apache.rya.api.instance.RyaDetailsUpdater.RyaDetailsMutator.CouldNotApplyMutationException;
+import org.apache.rya.api.model.VisibilityBindingSet;
+import org.apache.rya.api.persist.RyaDAOException;
+import org.apache.rya.indexing.pcj.storage.PcjMetadata;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjStorage;
+import org.apache.rya.mongodb.MongoDBRdfConfiguration;
+import org.apache.rya.mongodb.instance.MongoRyaInstanceDetailsRepository;
+import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
+import org.apache.rya.sail.config.RyaSailFactory;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.MalformedQueryException;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.query.QueryLanguage;
+import org.openrdf.query.TupleQuery;
+import org.openrdf.query.TupleQueryResultHandlerBase;
+import org.openrdf.query.TupleQueryResultHandlerException;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.repository.sail.SailRepositoryConnection;
+import org.openrdf.sail.Sail;
+import org.openrdf.sail.SailConnection;
+import org.openrdf.sail.SailException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.mongodb.MongoClient;
+
+/**
+ * A Mongo implementation of {@link MongoBatchUpdatePCJ}.
+ * <p>
+ * <b>Note:</b>
+ * <p>
+ * Using this batch updater can create data leaks since the Sail layer does not
+ * support {@link VisibilityBindingSet}s.
+ */
+public class MongoBatchUpdatePCJ implements BatchUpdatePCJ {
+    private static final Logger log = LoggerFactory.getLogger(MongoBatchUpdatePCJ.class);
+
+    private final MongoConnectionDetails connectionDetails;
+    private final MongoClient mongoClient;
+    private final InstanceExists instanceExists;
+
+    /**
+     * Constructs an instance of {@link MongoBatchUpdatePCJ}.
+     *
+     * @param connectionDetails - Details to connect to the server. (not null)
+     * @param instanceExists - The interactor used to check if a Rya instance exists. (not null)
+     * @param mongoClient - The {@link MongoClient} to use when batch updating. (not null)
+     */
+    public MongoBatchUpdatePCJ(
+            final MongoConnectionDetails connectionDetails,
+            final MongoClient mongoClient,
+            final MongoInstanceExists instanceExists) {
+        this.connectionDetails = requireNonNull(connectionDetails);
+        this.mongoClient = requireNonNull(mongoClient);
+        this.instanceExists = requireNonNull(instanceExists);
+    }
+
+    @Override
+    public void batchUpdate(final String ryaInstanceName, final String pcjId) throws InstanceDoesNotExistException, PCJDoesNotExistException, RyaClientException {
+        requireNonNull(ryaInstanceName);
+        requireNonNull(pcjId);
+
+        checkState(instanceExists.exists(ryaInstanceName), "The instance: " + ryaInstanceName + " does not exist.");
+
+        verifyPCJState(ryaInstanceName, pcjId, mongoClient);
+        updatePCJResults(ryaInstanceName, pcjId, mongoClient);
+        updatePCJMetadata(ryaInstanceName, pcjId, mongoClient);
+    }
+
+    private void verifyPCJState(final String ryaInstanceName, final String pcjId, final MongoClient client) throws RyaClientException {
+        try {
+            // Fetch the Rya instance's details.
+            final RyaDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(client, ryaInstanceName);
+            final RyaDetails ryaDetails = detailsRepo.getRyaInstanceDetails();
+
+            // Ensure PCJs are enabled.
+            if(!ryaDetails.getPCJIndexDetails().isEnabled()) {
+                throw new RyaClientException("PCJs are not enabled for the Rya instance named '" + ryaInstanceName + "'.");
+            }
+
+            // Ensure the PCJ exists.
+            if(!ryaDetails.getPCJIndexDetails().getPCJDetails().containsKey(pcjId)) {
+                throw new PCJDoesNotExistException("The PCJ with id '" + pcjId + "' does not exist within Rya instance '" + ryaInstanceName + "'.");
+            }
+
+        } catch(final NotInitializedException e) {
+            throw new InstanceDoesNotExistException("No RyaDetails are initialized for the Rya instance named '" + ryaInstanceName + "'.", e);
+        } catch (final RyaDetailsRepositoryException e) {
+            throw new RyaClientException("Could not fetch the RyaDetails for the Rya instance named '" + ryaInstanceName + "'.", e);
+        }
+    }
+
+    private void updatePCJResults(final String ryaInstanceName, final String pcjId, final MongoClient client) throws InstanceDoesNotExistException, PCJDoesNotExistException, RyaClientException {
+        // Things that have to be closed before we exit.
+        Sail sail = null;
+        SailConnection sailConn = null;
+
+        try(final PrecomputedJoinStorage pcjStorage = new MongoPcjStorage(client, ryaInstanceName)) {
+            // Create an instance of Sail backed by the Rya instance.
+            sail = connectToRya(ryaInstanceName);
+            final SailRepository sailRepo = new SailRepository(sail);
+            final SailRepositoryConnection sailRepoConn = sailRepo.getConnection();
+            // Purge the old results from the PCJ.
+            try {
+                pcjStorage.purge(pcjId);
+            } catch (final PCJStorageException e) {
+                throw new RyaClientException("Could not batch update PCJ with ID '" + pcjId + "' because the old " +
+                        "results could not be purged from it.", e);
+            }
+
+            // Parse the PCJ's SPARQL query.
+            final PcjMetadata metadata = pcjStorage.getPcjMetadata(pcjId);
+            final String sparql = metadata.getSparql();
+            sailConn = sail.getConnection();
+            final TupleQuery tupleQuery = sailRepoConn.prepareTupleQuery(QueryLanguage.SPARQL, sparql);
+
+            // Execute the query.
+            final List<VisibilityBindingSet> batch = new ArrayList<>(1000);
+            tupleQuery.evaluate(new TupleQueryResultHandlerBase() {
+                @Override
+                public void handleSolution(final BindingSet bindingSet) throws TupleQueryResultHandlerException {
+                    final VisibilityBindingSet result = new VisibilityBindingSet(bindingSet, "");
+                    log.warn("Visibility information on the binding set is lost during a batch update."
+                            + "  This can create data leaks.");
+                    batch.add(result);
+
+                    if(batch.size() == 1000) {
+                        try {
+                            pcjStorage.addResults(pcjId, batch);
+                        } catch (final PCJStorageException e) {
+                            throw new TupleQueryResultHandlerException("Fail to batch load new results into the PCJ with ID '" + pcjId + "'.", e);
+                        }
+                        batch.clear();
+                    }
+                }
+            });
+
+            if(!batch.isEmpty()) {
+                pcjStorage.addResults(pcjId, batch);
+                batch.clear();
+            }
+        } catch(final MalformedQueryException | PCJStorageException | SailException |
+                QueryEvaluationException | RepositoryException | TupleQueryResultHandlerException e) {
+            throw new RyaClientException("Fail to batch load new results into the PCJ with ID '" + pcjId + "'.", e);
+        } finally {
+            if(sailConn != null) {
+                try {
+                    sailConn.close();
+                } catch (final SailException e) {
+                    log.warn(e.getMessage(), e);
+                }
+            }
+
+            if(sail != null) {
+                try {
+                    sail.shutDown();
+                } catch (final SailException e) {
+                    log.warn(e.getMessage(), e);
+                }
+            }
+        }
+    }
+
+    private Sail connectToRya(final String ryaInstanceName) throws RyaClientException {
+        try {
+            final MongoDBRdfConfiguration ryaConf = connectionDetails.build(ryaInstanceName);
+            return RyaSailFactory.getInstance(ryaConf);
+        } catch (SailException | AccumuloException | AccumuloSecurityException | RyaDAOException | InferenceEngineException e) {
+            throw new RyaClientException("Could not connect to the Rya instance named '" + ryaInstanceName + "'.", e);
+        }
+    }
+
+    private void updatePCJMetadata(final String ryaInstanceName, final String pcjId, final MongoClient client) throws RyaClientException {
+        // Update the PCJ's metadata to indicate it was just batch updated.
+        try {
+            final RyaDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(client, ryaInstanceName);
+
+            new RyaDetailsUpdater(detailsRepo).update(new RyaDetailsMutator() {
+                @Override
+                public RyaDetails mutate(final RyaDetails originalDetails) throws CouldNotApplyMutationException {
+                    // Update the original PCJ Details to indicate they were batch updated.
+                    final PCJDetails originalPCJDetails = originalDetails.getPCJIndexDetails().getPCJDetails().get(pcjId);
+                    final PCJDetails.Builder mutatedPCJDetails = PCJDetails.builder( originalPCJDetails )
+                            .setUpdateStrategy( PCJUpdateStrategy.BATCH )
+                            .setLastUpdateTime( new Date());
+
+                    // Replace the old PCJ Details with the updated ones.
+                    final RyaDetails.Builder builder = RyaDetails.builder(originalDetails);
+                    builder.getPCJIndexDetails().addPCJDetails( mutatedPCJDetails );
+                    return builder.build();
+                }
+            });
+        } catch (final RyaDetailsRepositoryException | CouldNotApplyMutationException e) {
+            throw new RyaClientException("Could not update the PCJ's metadata.", e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoCreatePCJ.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoCreatePCJ.java b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoCreatePCJ.java
new file mode 100644
index 0000000..49e7551
--- /dev/null
+++ b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoCreatePCJ.java
@@ -0,0 +1,77 @@
+/**
+ * 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.
+ */
+package org.apache.rya.api.client.mongo;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Set;
+
+import org.apache.rya.api.client.CreatePCJ;
+import org.apache.rya.api.client.InstanceDoesNotExistException;
+import org.apache.rya.api.client.InstanceExists;
+import org.apache.rya.api.client.RyaClientException;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjStorage;
+
+import com.google.common.collect.Sets;
+import com.mongodb.MongoClient;
+
+/**
+ * A Mongo implementation of {@link CreatePCJ}.
+ */
+public class MongoCreatePCJ implements CreatePCJ {
+    private final InstanceExists instanceExists;
+    private final MongoClient mongoClient;
+
+    /**
+     * Constructs an instance of {@link MongoCreatePCJ}.
+     *
+     * @param mongoClient - The {@link MongoClient} used to create a new PCJ. (not null)
+     * @param instanceExists - The interactor used to check if a Rya instance exists. (not null)
+     */
+    public MongoCreatePCJ(
+            final MongoClient mongoClient,
+            final MongoInstanceExists instanceExists) {
+        this.mongoClient = requireNonNull(mongoClient);
+        this.instanceExists = requireNonNull(instanceExists);
+    }
+
+    @Override
+    public String createPCJ(final String ryaInstanceName, final String sparql, final Set<ExportStrategy> strategies) throws InstanceDoesNotExistException, RyaClientException {
+        requireNonNull(ryaInstanceName);
+        requireNonNull(sparql);
+
+        // Ensure the Rya Instance exists.
+        if (!instanceExists.exists(ryaInstanceName)) {
+            throw new InstanceDoesNotExistException(String.format("There is no Rya instance named '%s'.", ryaInstanceName));
+        }
+
+        try(final MongoPcjStorage pcjStore = new MongoPcjStorage(mongoClient, ryaInstanceName)) {
+        	return pcjStore.createPcj(sparql);
+        } catch (final PCJStorageException e) {
+            throw new RyaClientException("Unable to create PCJ for: " + sparql, e);
+        }
+    }
+
+    @Override
+    public String createPCJ(final String instanceName, final String sparql) throws InstanceDoesNotExistException, RyaClientException {
+        return createPCJ(instanceName, sparql, Sets.newHashSet(ExportStrategy.RYA));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoDeletePCJ.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoDeletePCJ.java b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoDeletePCJ.java
new file mode 100644
index 0000000..8c0a71d
--- /dev/null
+++ b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoDeletePCJ.java
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+package org.apache.rya.api.client.mongo;
+
+import static java.util.Objects.requireNonNull;
+
+import org.apache.rya.api.client.DeletePCJ;
+import org.apache.rya.api.client.InstanceDoesNotExistException;
+import org.apache.rya.api.client.InstanceExists;
+import org.apache.rya.api.client.RyaClientException;
+import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException;
+import org.apache.rya.indexing.pcj.storage.mongo.MongoPcjStorage;
+
+import com.mongodb.MongoClient;
+
+/**
+ * A Mongo implementation of {@link DeletePCJ}.
+ */
+public class MongoDeletePCJ implements DeletePCJ {
+    private final InstanceExists instanceExists;
+    private final MongoClient mongoClient;
+
+    /**
+     * Constructs an instance of {@link MongoDeletePCJ}.
+     *
+     * @param mongoClient - The {@link MongoClient} to use to delete a PCJ. (not null) 
+     * @param instanceExists - The interactor used to check if a Rya instance exists. (not null)
+     */
+    public MongoDeletePCJ(
+            final MongoClient mongoClient,
+            final MongoInstanceExists instanceExists) { 
+        this.mongoClient = requireNonNull(mongoClient);
+        this.instanceExists = requireNonNull(instanceExists);
+    }
+
+    @Override
+    public void deletePCJ(final String ryaInstanceName, final String pcjId) throws InstanceDoesNotExistException, RyaClientException {
+        requireNonNull(ryaInstanceName);
+        requireNonNull(pcjId);
+
+        // Ensure the Rya Instance exists.
+        if (!instanceExists.exists(ryaInstanceName)) {
+            throw new InstanceDoesNotExistException(String.format("There is no Rya instance named '%s'.", ryaInstanceName));
+        }
+
+        try(final MongoPcjStorage pcjStore = new MongoPcjStorage(mongoClient, ryaInstanceName)) {
+            pcjStore.dropPcj(pcjId);
+        } catch (final PCJStorageException e) {
+            throw new RyaClientException("Unable to drop PCJ : " + pcjId, e);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoInstall.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoInstall.java b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoInstall.java
index 51bd4bf..264dd78 100644
--- a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoInstall.java
+++ b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoInstall.java
@@ -107,7 +107,7 @@ public class MongoInstall implements Install {
             // This can only happen if somebody else installs an instance of Rya with the name between the check and now.
             throw new DuplicateInstanceNameException(
                     "An instance of Rya has already been installed to this Rya storage " +
-                    "with the name '" + instanceName + "'. Try again with a different name.");
+                            "with the name '" + instanceName + "'. Try again with a different name.");
         } catch (final RyaDetailsRepositoryException e) {
             throw new RyaClientException("The RyaDetails couldn't be initialized. Details: " + e.getMessage(), e);
         }
@@ -147,27 +147,28 @@ public class MongoInstall implements Install {
             final InstallConfiguration installConfig) throws AlreadyInitializedException, RyaDetailsRepositoryException {
         final RyaDetailsRepository detailsRepo = new MongoRyaInstanceDetailsRepository(adminClient, instanceName);
 
-        // Build the PCJ Index details. [not supported in mongo]
-        final PCJIndexDetails.Builder pcjDetailsBuilder = PCJIndexDetails.builder().setEnabled(false);
+        if(installConfig.getFluoPcjAppName().isPresent()) {
+        	log.warn("Mongo does not have fluo support, use ignoring the configured fluo application name: " + installConfig.getFluoPcjAppName().get());
+        }
+        
+        // Build the PCJ Index details.
+        final PCJIndexDetails.Builder pcjDetailsBuilder = PCJIndexDetails.builder()
+                .setEnabled(installConfig.isPcjIndexEnabled());
 
         final RyaDetails details = RyaDetails.builder()
                 // General Metadata
                 .setRyaInstanceName(instanceName).setRyaVersion(getVersion())
 
-                // FIXME RYA-215 .setGeoIndexDetails(new GeoIndexDetails(installConfig.isGeoIndexEnabled()))
-
                 // Secondary Index Values
+                // FIXME RYA-215 .setGeoIndexDetails(new GeoIndexDetails(installConfig.isGeoIndexEnabled()))
                 .setTemporalIndexDetails(new TemporalIndexDetails(installConfig.isTemporalIndexEnabled()))
-                .setFreeTextDetails(new FreeTextIndexDetails(installConfig.isFreeTextIndexEnabled()))//
-
-                // Entity centric indexing is not supported in Mongo DB.
+                .setFreeTextDetails(new FreeTextIndexDetails(installConfig.isFreeTextIndexEnabled()))
                 .setEntityCentricIndexDetails(new EntityCentricIndexDetails(false))
-
                 .setPCJIndexDetails(pcjDetailsBuilder)
 
                 // Statistics values.
-                .setProspectorDetails(new ProspectorDetails(Optional.<Date> absent()))//
-                .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.<Date> absent()))//
+                .setProspectorDetails(new ProspectorDetails(Optional.<Date> absent()))
+                .setJoinSelectivityDetails(new JoinSelectivityDetails(Optional.<Date> absent()))
                 .build();
 
         // Initialize the table.
@@ -191,26 +192,23 @@ public class MongoInstall implements Install {
 
         final MongoDBRdfConfiguration conf = connectionDetails.build(ryaDetails.getRyaInstanceName());
 
-        // The Mongo implementation of Rya does not currently support PCJs.
-        if(ryaDetails.getPCJIndexDetails().isEnabled()) {
-            log.warn("The install configuration says to enable PCJ indexing, but Mongo RYA does not support that " +
-                    "feature. Ignoring this configuration.");
-        }
-        conf.set(ConfigUtils.USE_PCJ, "false");
+        conf.setBoolean(ConfigUtils.USE_PCJ, ryaDetails.getPCJIndexDetails().isEnabled());
 
         // Mongo does not support entity indexing.
         if(ryaDetails.getEntityCentricIndexDetails().isEnabled()) {
             log.warn("The install configuration says to enable Entity Centric indexing, but Mongo RYA does not support " +
                     "that feature. Ignoring this configuration.");
         }
-        conf.set(ConfigUtils.USE_ENTITY, "false");
+
+        //TODO mongo now has an entity index, just needs CLI support.
+        conf.setBoolean(ConfigUtils.USE_ENTITY, false);
 
         // FIXME RYA-215 We haven't enabled geo indexing in the console yet.
         //conf.set(OptionalConfigUtils.USE_GEO, "" + details.getGeoIndexDetails().isEnabled() );
 
         // Enable the supported indexers that the instance is configured to use.
-        conf.set(ConfigUtils.USE_FREETEXT, "" + ryaDetails.getFreeTextIndexDetails().isEnabled());
-        conf.set(ConfigUtils.USE_TEMPORAL, "" + ryaDetails.getTemporalIndexDetails().isEnabled());
+        conf.setBoolean(ConfigUtils.USE_FREETEXT, ryaDetails.getFreeTextIndexDetails().isEnabled());
+        conf.setBoolean(ConfigUtils.USE_TEMPORAL, ryaDetails.getTemporalIndexDetails().isEnabled());
 
         // This initializes the living indexers that will be used by the application and
         // caches them within the configuration object so that they may be used later.

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoRyaClientFactory.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoRyaClientFactory.java b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoRyaClientFactory.java
index 55c6e8a..fbbec2a 100644
--- a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoRyaClientFactory.java
+++ b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoRyaClientFactory.java
@@ -55,12 +55,12 @@ public class MongoRyaClientFactory {
 
         return new RyaClient(
                 new MongoInstall(connectionDetails, adminClient, instanceExists),
+                new MongoCreatePCJ(adminClient, instanceExists),
+                new MongoDeletePCJ(adminClient, instanceExists),
                 Optional.empty(),
                 Optional.empty(),
                 Optional.empty(),
-                Optional.empty(),
-                Optional.empty(),
-                Optional.empty(),
+                new MongoBatchUpdatePCJ(connectionDetails, adminClient, instanceExists),
                 new MongoGetInstanceDetails(adminClient, instanceExists),
                 instanceExists,
                 new MongoListInstances(adminClient),

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java
index 5cc1c44..561f6c6 100644
--- a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java
+++ b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/ConfigUtils.java
@@ -80,25 +80,25 @@ public class ConfigUtils {
      */
     @Deprecated
     public static final String CLOUDBASE_TBL_PREFIX = RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX;
-    
+
     /**
      * @Deprecated use {@link AccumuloRdfConfiguration#CLOUDBASE_INSTANCE} instead.
      */
     @Deprecated
     public static final String CLOUDBASE_INSTANCE = AccumuloRdfConfiguration.CLOUDBASE_INSTANCE;
-    
+
     /**
      * @Deprecated use {@link AccumuloRdfConfiguration#CLOUDBASE_ZOOKEEPERS} instead.
      */
     @Deprecated
     public static final String CLOUDBASE_ZOOKEEPERS = AccumuloRdfConfiguration.CLOUDBASE_ZOOKEEPERS;
-    
+
     /**
      * @Deprecated use {@link AccumuloRdfConfiguration#CLOUDBASE_USER} instead.
      */
     @Deprecated
     public static final String CLOUDBASE_USER = AccumuloRdfConfiguration.CLOUDBASE_USER;
-    
+
     /**
      * @Deprecated use {@link AccumuloRdfConfiguration#CLOUDBASE_PASSWORD} instead.
      */
@@ -192,7 +192,7 @@ public class ConfigUtils {
      * null. Future, get table prefix from RyaDetails -- the Rya instance name
      * -- also getting info from the RyaDetails should happen within
      * RyaSailFactory and not ConfigUtils.
-     * 
+     *
      * @param conf
      *            Rya configuration map where it extracts the prefix (instance
      *            name)
@@ -220,7 +220,7 @@ public class ConfigUtils {
 
     /**
      * Used for indexing statements about date & time instances and intervals.
-     * 
+     *
      * @param conf
      * @return Set of predicate URI's whose objects should be date time
      *         literals.
@@ -337,8 +337,8 @@ public class ConfigUtils {
     public static Instance getInstance(final Configuration conf) {
         // Pull out the Accumulo specific configuration values.
         final AccumuloRdfConfiguration accConf = new AccumuloRdfConfiguration(conf);
-        String instanceName = accConf.getInstanceName();
-        String zoookeepers = accConf.getZookeepers();
+        final String instanceName = accConf.getInstanceName();
+        final String zoookeepers = accConf.getZookeepers();
 
         // Create an Instance a mock if the mock flag is set.
         if (useMockInstance(conf)) {
@@ -466,6 +466,10 @@ public class ConfigUtils {
                 indexList.add(MongoTemporalIndexer.class.getName());
                 useFilterIndex = true;
             }
+
+            if (getUsePCJ(conf) && getUseOptimalPCJ(conf)) {
+                conf.setPcjOptimizer(PCJOptimizer.class);
+            }
         } else {
             if (getUsePCJ(conf) || getUseOptimalPCJ(conf)) {
                 conf.setPcjOptimizer(PCJOptimizer.class);


[4/8] incubator-rya git commit: RYA-303 Mongo PCJ Support. Closes #172.

Posted by ca...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest2.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest2.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest2.java
index 35e4ca3..2988ff3 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest2.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerTest2.java
@@ -1,6 +1,4 @@
-package org.apache.rya.indexing.external;
-
-/*
+/**
  * 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
@@ -18,18 +16,27 @@ package org.apache.rya.indexing.external;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.rya.indexing.external;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.rya.indexing.external.PcjIntegrationTestingUtil.BindingSetAssignmentCollector;
 import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
+import org.apache.rya.indexing.mongodb.pcj.MongoPcjIndexSetProvider;
 import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
-
+import org.apache.rya.indexing.pcj.matching.provider.AbstractPcjIndexSetProvider;
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
+import org.apache.rya.mongodb.EmbeddedMongoSingleton;
+import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
 import org.junit.Assert;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 import org.openrdf.query.algebra.Projection;
 import org.openrdf.query.algebra.QueryModelNode;
 import org.openrdf.query.algebra.StatementPattern;
@@ -38,1095 +45,1127 @@ import org.openrdf.query.algebra.helpers.StatementPatternCollector;
 import org.openrdf.query.parser.ParsedQuery;
 import org.openrdf.query.parser.sparql.SPARQLParser;
 
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
+@RunWith(Parameterized.class)
 public class PrecompJoinOptimizerTest2 {
+    private final AbstractPcjIndexSetProvider provider;
+
+    @Parameterized.Parameters
+    public static Collection providers() throws Exception {
+        final StatefulMongoDBRdfConfiguration conf = new StatefulMongoDBRdfConfiguration(new Configuration(), EmbeddedMongoSingleton.getNewMongoClient());
+        return Lists.<AbstractPcjIndexSetProvider> newArrayList(
+                new AccumuloIndexSetProvider(new Configuration()),
+                new MongoPcjIndexSetProvider(conf)
+                );
+    }
+
+    public PrecompJoinOptimizerTest2(final AbstractPcjIndexSetProvider provider) {
+        this.provider = provider;
+    }
+
+    private final String queryString = ""//
+            + "SELECT ?e ?c ?l ?o " //
+            + "{" //
+            + "  ?e a ?c . "//
+            + "  ?c a ?l . "//
+            + "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+            + "  ?e <uri:talksTo> ?o  "//
+            + "}";//
+
+    private final String indexSparqlString = ""//
+            + "SELECT ?x ?y ?z " //
+            + "{" //
+            + "  ?x <http://www.w3.org/2000/01/rdf-schema#label> ?z. "//
+            + "  ?x a ?y . "//
+            + "  ?y a ?z  "//
+            + "}";//
+
+    private final String q1 = ""//
+            + "SELECT ?e ?l ?c " //
+            + "{" //
+            + "  ?e a ?c . "//
+            + "  ?c <http://www.w3.org/2000/01/rdf-schema#label> ?l. "//
+            + "  ?l <uri:talksTo> ?e . "//
+            + "}";//
+
+    private final String q2 = ""//
+            + "SELECT ?a ?t ?v  " //
+            + "{" //
+            + "  ?a a ?t . "//
+            + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?v . "//
+            + "  ?v <uri:talksTo> ?a . "//
+            + "}";//
+
+    private final String q5 = ""//
+            + "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r " //
+            + "{" //
+            + "  ?f a ?m ."//
+            + "  ?e a ?l ."//
+            + "  ?n a ?o ."//
+            + "  ?a a ?h ."//
+            + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+            + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+            + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
+            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
+            + "  ?d <uri:talksTo> ?f . "//
+            + "  ?c <uri:talksTo> ?e . "//
+            + "  ?p <uri:talksTo> ?n . "//
+            + "  ?r <uri:talksTo> ?a . "//
+            + "}";//
+
+    private final String q7 = ""//
+            + "SELECT ?s ?t ?u " //
+            + "{" //
+            + "  ?s a ?t ."//
+            + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+            + "  ?u <uri:talksTo> ?s . "//
+            + "}";//
+
+    private final String q8 = ""//
+            + "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r " //
+            + "{" //
+            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
+            + "  ?f a ?m ."//
+            + "  ?p <uri:talksTo> ?n . "//
+            + "  ?e a ?l ."//
+            + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
+            + "  ?d <uri:talksTo> ?f . "//
+            + "  ?c <uri:talksTo> ?e . "//
+            + "  ?n a ?o ."//
+            + "  ?a a ?h ."//
+            + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+            + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+            + "  ?r <uri:talksTo> ?a . "//
+            + "}";//
+
+    private final String q11 = ""//
+            + "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r ?x ?y ?w ?t ?duck ?chicken ?pig ?rabbit " //
+            + "{" //
+            + "  ?w a ?t ."//
+            + "  ?x a ?y ."//
+            + "  ?duck a ?chicken ."//
+            + "  ?pig a ?rabbit ."//
+            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
+            + "  ?f a ?m ."//
+            + "  ?p <uri:talksTo> ?n . "//
+            + "  ?e a ?l ."//
+            + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
+            + "  ?d <uri:talksTo> ?f . "//
+            + "  ?c <uri:talksTo> ?e . "//
+            + "  ?n a ?o ."//
+            + "  ?a a ?h ."//
+            + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+            + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+            + "  ?r <uri:talksTo> ?a . "//
+            + "}";//
+
+    private final String q12 = ""//
+            + "SELECT ?b ?p ?dog ?cat " //
+            + "{" //
+            + "  ?b a ?p ."//
+            + "  ?dog a ?cat. "//
+            + "}";//
+
+    private final String q13 = ""//
+            + "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r ?x ?y ?w ?t ?duck ?chicken ?pig ?rabbit ?dick ?jane ?betty " //
+            + "{" //
+            + "  ?w a ?t ."//
+            + "  ?x a ?y ."//
+            + "  ?duck a ?chicken ."//
+            + "  ?pig a ?rabbit ."//
+            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
+            + "  ?f a ?m ."//
+            + "  ?p <uri:talksTo> ?n . "//
+            + "  ?e a ?l ."//
+            + "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
+            + "  ?d <uri:talksTo> ?f . "//
+            + "  ?c <uri:talksTo> ?e . "//
+            + "  ?n a ?o ."//
+            + "  ?a a ?h ."//
+            + "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+            + "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+            + "  ?r <uri:talksTo> ?a . "//
+            + "  ?dick <uri:talksTo> ?jane . "//
+            + "  ?jane <uri:talksTo> ?betty . "//
+            + "}";//
+
+    private final String q14 = ""//
+            + "SELECT ?harry ?susan ?mary " //
+            + "{" //
+            + "  ?harry <uri:talksTo> ?susan . "//
+            + "  ?susan <uri:talksTo> ?mary . "//
+            + "}";//
+
+    String q15 = ""//
+            + "SELECT ?a ?b ?c ?d ?e ?f ?q " //
+            + "{" //
+            + " GRAPH ?x { " //
+            + "  ?a a ?b ."//
+            + "  ?b <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+            + "  ?d <uri:talksTo> ?e . "//
+            + "  FILTER ( ?e < ?f && (?a > ?b || ?c = ?d) ). " //
+            + "  FILTER(bound(?f) && sameTerm(?a,?b)&&bound(?q)). " //
+            + "  ?b a ?q ."//
+            + "		}"//
+            + "}";//
+
+    String q16 = ""//
+            + "SELECT ?g ?h ?i " //
+            + "{" //
+            + " GRAPH ?y { " //
+            + "  ?g a ?h ."//
+            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?i ."//
+            + "		}"//
+            + "}";//
+
+    String q17 = ""//
+            + "SELECT ?j ?k ?l ?m ?n ?o " //
+            + "{" //
+            + " GRAPH ?z { " //
+            + "  ?j <uri:talksTo> ?k . "//
+            + "  FILTER ( ?k < ?l && (?m > ?n || ?o = ?j) ). " //
+            + "		}"//
+            + "}";//
+
+    String q18 = ""//
+            + "SELECT ?r ?s ?t ?u " //
+            + "{" //
+            + " GRAPH ?q { " //
+            + "  FILTER(bound(?r) && sameTerm(?s,?t)&&bound(?u)). " //
+            + "  ?t a ?u ."//
+            + "		}"//
+            + "}";//
+
+    String q19 = ""//
+            + "SELECT ?a ?b ?c ?d ?e ?f ?q ?g ?h " //
+            + "{" //
+            + " GRAPH ?x { " //
+            + "  ?a a ?b ."//
+            + "  ?b <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+            + "  ?d <uri:talksTo> ?e . "//
+            + "  FILTER ( ?e < ?f && (?a > ?b || ?c = ?d) ). " //
+            + "  FILTER(bound(?f) && sameTerm(?a,?b)&&bound(?q)). " //
+            + "  FILTER(?g IN (1,2,3) && ?h NOT IN(5,6,7)). " //
+            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?g. "//
+            + "  ?b a ?q ."//
+            + "		}"//
+            + "}";//
+
+    String q20 = ""//
+            + "SELECT ?m ?n " //
+            + "{" //
+            + " GRAPH ?q { " //
+            + "  FILTER(?m IN (1,2,3) && ?n NOT IN(5,6,7)). " //
+            + "  ?n <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
+            + "		}"//
+            + "}";//
+
+    String q21 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
+            + "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>  "//
+            + "SELECT ?feature ?point ?wkt " //
+            + "{" //
+            + "  ?feature a geo:Feature . "//
+            + "  ?feature geo:hasGeometry ?point . "//
+            + "  ?point a geo:Point . "//
+            + "  ?point geo:asWKT ?wkt . "//
+            + "  FILTER(geof:sfWithin(?wkt, \"Polygon\")) " //
+            + "}";//
+
+    String q22 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "SELECT ?person ?commentmatch ?labelmatch" //
+            + "{" //
+            + "  ?person a <http://example.org/ontology/Person> . "//
+            + "  ?person <http://www.w3.org/2000/01/rdf-schema#label> ?labelmatch . "//
+            + "  ?person <http://www.w3.org/2000/01/rdf-schema#comment> ?commentmatch . "//
+            + "  FILTER(fts:text(?labelmatch, \"bob\")) . " //
+            + "  FILTER(fts:text(?commentmatch, \"bob\"))  " //
+            + "}";//
+
+    String q23 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
+            + "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>  "//
+            + "SELECT ?a ?b ?c " //
+            + "{" //
+            + "  ?a a geo:Feature . "//
+            + "  ?b a geo:Point . "//
+            + "  ?b geo:asWKT ?c . "//
+            + "  FILTER(geof:sfWithin(?c, \"Polygon\")) " //
+            + "}";//
+
+    String q24 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "SELECT ?f ?g " //
+            + "{" //
+            + "  ?f <http://www.w3.org/2000/01/rdf-schema#comment> ?g . "//
+            + "  FILTER(fts:text(?g, \"bob\"))  " //
+            + "}";//
+
+    String q25 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "SELECT ?person ?commentmatch ?labelmatch ?point" //
+            + "{" //
+            + "  ?person a ?point. " //
+            + "  ?person a <http://example.org/ontology/Person> . "//
+            + "  ?person <http://www.w3.org/2000/01/rdf-schema#label> ?labelmatch . "//
+            + "  ?person <http://www.w3.org/2000/01/rdf-schema#comment> ?commentmatch . "//
+            + "  FILTER((?person > ?point) || (?person = ?labelmatch)). "
+            + "  FILTER(fts:text(?labelmatch, \"bob\")) . " //
+            + "  FILTER(fts:text(?commentmatch, \"bob\"))  " //
+            + "}";//
+
+    String q26 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "SELECT ?a ?b ?c  " //
+            + "{" //
+            + "  ?a a ?c. " //
+            + "  ?a a <http://example.org/ontology/Person> . "//
+            + "  ?a <http://www.w3.org/2000/01/rdf-schema#label> ?b . "//
+            + "  FILTER((?a > ?c) || (?a = ?b)). "
+            + "  FILTER(fts:text(?b, \"bob\")) . " //
+            + "}";//
+
+    String q27 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
+            + "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>  "//
+            + "SELECT ?person ?commentmatch ?labelmatch ?other ?feature ?point ?wkt ?g ?h" //
+            + "{" //
+            + "  ?person a <http://example.org/ontology/Person> . "//
+            + "  ?person <http://www.w3.org/2000/01/rdf-schema#label> ?labelmatch . "//
+            + "  ?person <http://www.w3.org/2000/01/rdf-schema#comment> ?commentmatch . "//
+            + "  FILTER((?person > ?other) || (?person = ?labelmatch)). "
+            + "  ?person a ?other. "//
+            + "  FILTER(fts:text(?labelmatch, \"bob\")) . " //
+            + "  FILTER(fts:text(?commentmatch, \"bob\"))  " //
+            + " ?feature a geo:Feature . "//
+            + "  ?point a geo:Point . "//
+            + "  ?point geo:asWKT ?wkt . "//
+            + "  FILTER(geof:sfWithin(?wkt, \"Polygon\")) " //
+            + "  FILTER(?g IN (1,2,3) && ?h NOT IN(5,6,7)). " //
+            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?g. "//
+            + "}";//
+
+    String q28 = ""//
+            + "SELECT ?m ?n " //
+            + "{" //
+            + "  FILTER(?m IN (1,2,3) && ?n NOT IN(5,6,7)). " //
+            + "  ?n <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
+            + "}";//
+
+    String q29 = ""//
+            + "SELECT ?m ?n ?o" //
+            + "{" //
+            + "  FILTER(?m IN (1,2,3) && ?n NOT IN(5,6,7)). " //
+            + "  ?n <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
+            + "  ?m a ?o." //
+            + "  FILTER(ISNUMERIC(?o))." + "}";//
+
+    String q30 = ""//
+            + "SELECT ?pig ?dog ?owl" //
+            + "{" //
+            + "  FILTER(?pig IN (1,2,3) && ?dog NOT IN(5,6,7)). " //
+            + "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig. "//
+            + "  ?pig a ?owl. " //
+            + "  FILTER(ISNUMERIC(?owl))." + "}";//
+
+    String q31 = ""//
+            + "SELECT ?q ?r ?s " //
+            + "{" //
+            + "  {?q a ?r} UNION {?r a ?s} ."//
+            + "  ?r a ?s ."//
+            + "}";//
+
+    String q33 = ""//
+            + "SELECT ?q ?r ?s ?t " //
+            + "{" //
+            + "  OPTIONAL {?q a ?r} ."//
+            + "  ?s a ?t ."//
+            + "}";//
+
+    String q34 = ""//
+            + "SELECT ?q ?r  " //
+            + "{" //
+            + "  FILTER(?q > ?r) ."//
+            + "  ?q a ?r ."//
+            + "}";//
+
+    String q35 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "SELECT ?s ?t ?u ?v ?w ?x ?y ?z " //
+            + "{" //
+            + "  FILTER(?s > ?t)."//
+            + "  ?s a ?t ."//
+            + "  FILTER(?u > ?v)."//
+            + "  ?u a ?v ."//
+            + "  ?w <http://www.w3.org/2000/01/rdf-schema#label> ?x ."//
+            + "  FILTER(fts:text(?x, \"bob\")) . " //
+            + "  ?y <http://www.w3.org/2000/01/rdf-schema#label> ?z ."//
+            + "  FILTER(fts:text(?z, \"bob\")) . " //
+            + "}";//
+
+    String q36 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "SELECT ?dog ?cat  " //
+            + "{" //
+            + "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?cat ."//
+            + "  FILTER(fts:text(?cat, \"bob\")) . " //
+            + "}";//
+
+    String q37 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "SELECT ?s ?t " //
+            + "{" //
+            + "  FILTER(?s > ?t)."//
+            + "  ?s a ?t ."//
+            + "  FILTER(?s > ?t)."//
+            + "  ?s a ?t ."//
+            + "  FILTER(?s > ?t)."//
+            + "  ?s a ?t ."//
+            + "}";//
+
+    String q38 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
+            + "SELECT ?s ?t " //
+            + "{" //
+            + "  FILTER(?s > ?t)."//
+            + "  ?s a ?t ."//
+            + "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?s ."//
+            + "  FILTER(?s > ?t)."//
+            + "}";//
+
+    String q39 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
+            + "SELECT ?s ?t " //
+            + "{" //
+            + " VALUES(?s) { (<ub:poodle>)(<ub:pitbull>)} ." //
+            + " ?t <ub:peesOn> <ub:rug> ." //
+            + " ?t <http://www.w3.org/2000/01/rdf-schema#label> ?s ."//
+            + "}";//
+
+    String q40 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
+            + "SELECT ?u ?v " //
+            + "{" //
+            + " ?v <ub:peesOn> <ub:rug> ." //
+            + " ?v <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+            + "}";//
+
+    String q41 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
+            + "SELECT ?s ?t ?w ?x" //
+            + "{" //
+            + " FILTER(?s > ?t)."//
+            + " VALUES(?s) { (<ub:poodle>)(<ub:pitbull>)} ." //
+            + " VALUES(?w) { (<ub:persian>) (<ub:siamese>) } ." //
+            + " ?t <ub:peesOn> <ub:rug> ." //
+            + " ?t <http://www.w3.org/2000/01/rdf-schema#label> ?s ."//
+            + " ?w <ub:peesOn> <ub:rug> ." //
+            + " ?w <http://www.w3.org/2000/01/rdf-schema#label> ?x ."//
+            + "}";//
+
+    String q42 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
+            + "SELECT ?u ?v " //
+            + "{" //
+            + " FILTER(?u > ?v)."//
+            + " ?v <ub:peesOn> <ub:rug> ." //
+            + " ?v <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+            + "}";//
+
+    String q43 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
+            + "SELECT ?a ?b " //
+            + "{" //
+            + " ?b <ub:peesOn> <ub:rug> ." //
+            + " ?b <http://www.w3.org/2000/01/rdf-schema#label> ?a ."//
+            + "}";//
+
+    @Test
+    public void testVarRelableIndexSmaller() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(queryString, null);
+        final ParsedQuery pq2 = parser2.parseQuery(indexSparqlString, null);
+
+        System.out.println("Query is " + pq1.getTupleExpr());
+        System.out.println("Index is " + pq2.getTupleExpr());
+
+        final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets
+                .newHashSet(StatementPatternCollector.process(pq1
+                        .getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(qSet.containsAll(set) && set.size() != 0);
+    }
+
+    @Test
+    public void testVarRelableIndexSameSize() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q1, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q2, null);
+
+        final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets
+                .newHashSet(StatementPatternCollector.process(pq1
+                        .getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(set.equals(qSet));
+
+    }
+
+    @Test
+    public void testTwoIndexLargeQuery() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+        final SPARQLParser parser3 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q11, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q7, null);
+        final ParsedQuery pq3 = parser3.parseQuery(q12, null);
 
-	private final String queryString = ""//
-			+ "SELECT ?e ?c ?l ?o " //
-			+ "{" //
-			+ "  ?e a ?c . "//
-			+ "  ?c a ?l . "//
-			+ "  ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
-			+ "  ?e <uri:talksTo> ?o  "//
-			+ "}";//
-
-	private final String indexSparqlString = ""//
-			+ "SELECT ?x ?y ?z " //
-			+ "{" //
-			+ "  ?x <http://www.w3.org/2000/01/rdf-schema#label> ?z. "//
-			+ "  ?x a ?y . "//
-			+ "  ?y a ?z  "//
-			+ "}";//
-
-	private final String q1 = ""//
-			+ "SELECT ?e ?l ?c " //
-			+ "{" //
-			+ "  ?e a ?c . "//
-			+ "  ?c <http://www.w3.org/2000/01/rdf-schema#label> ?l. "//
-			+ "  ?l <uri:talksTo> ?e . "//
-			+ "}";//
-
-	private final String q2 = ""//
-			+ "SELECT ?a ?t ?v  " //
-			+ "{" //
-			+ "  ?a a ?t . "//
-			+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?v . "//
-			+ "  ?v <uri:talksTo> ?a . "//
-			+ "}";//
-
-	private final String q5 = ""//
-			+ "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r " //
-			+ "{" //
-			+ "  ?f a ?m ."//
-			+ "  ?e a ?l ."//
-			+ "  ?n a ?o ."//
-			+ "  ?a a ?h ."//
-			+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-			+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-			+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
-			+ "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
-			+ "  ?d <uri:talksTo> ?f . "//
-			+ "  ?c <uri:talksTo> ?e . "//
-			+ "  ?p <uri:talksTo> ?n . "//
-			+ "  ?r <uri:talksTo> ?a . "//
-			+ "}";//
-
-	private final String q7 = ""//
-			+ "SELECT ?s ?t ?u " //
-			+ "{" //
-			+ "  ?s a ?t ."//
-			+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-			+ "  ?u <uri:talksTo> ?s . "//
-			+ "}";//
-
-	private final String q8 = ""//
-			+ "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r " //
-			+ "{" //
-			+ "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
-			+ "  ?f a ?m ."//
-			+ "  ?p <uri:talksTo> ?n . "//
-			+ "  ?e a ?l ."//
-			+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
-			+ "  ?d <uri:talksTo> ?f . "//
-			+ "  ?c <uri:talksTo> ?e . "//
-			+ "  ?n a ?o ."//
-			+ "  ?a a ?h ."//
-			+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-			+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-			+ "  ?r <uri:talksTo> ?a . "//
-			+ "}";//
-
-	private final String q11 = ""//
-			+ "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r ?x ?y ?w ?t ?duck ?chicken ?pig ?rabbit " //
-			+ "{" //
-			+ "  ?w a ?t ."//
-			+ "  ?x a ?y ."//
-			+ "  ?duck a ?chicken ."//
-			+ "  ?pig a ?rabbit ."//
-			+ "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
-			+ "  ?f a ?m ."//
-			+ "  ?p <uri:talksTo> ?n . "//
-			+ "  ?e a ?l ."//
-			+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
-			+ "  ?d <uri:talksTo> ?f . "//
-			+ "  ?c <uri:talksTo> ?e . "//
-			+ "  ?n a ?o ."//
-			+ "  ?a a ?h ."//
-			+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-			+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-			+ "  ?r <uri:talksTo> ?a . "//
-			+ "}";//
-
-	private final String q12 = ""//
-			+ "SELECT ?b ?p ?dog ?cat " //
-			+ "{" //
-			+ "  ?b a ?p ."//
-			+ "  ?dog a ?cat. "//
-			+ "}";//
-
-	private final String q13 = ""//
-			+ "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r ?x ?y ?w ?t ?duck ?chicken ?pig ?rabbit ?dick ?jane ?betty " //
-			+ "{" //
-			+ "  ?w a ?t ."//
-			+ "  ?x a ?y ."//
-			+ "  ?duck a ?chicken ."//
-			+ "  ?pig a ?rabbit ."//
-			+ "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
-			+ "  ?f a ?m ."//
-			+ "  ?p <uri:talksTo> ?n . "//
-			+ "  ?e a ?l ."//
-			+ "  ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
-			+ "  ?d <uri:talksTo> ?f . "//
-			+ "  ?c <uri:talksTo> ?e . "//
-			+ "  ?n a ?o ."//
-			+ "  ?a a ?h ."//
-			+ "  ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
-			+ "  ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-			+ "  ?r <uri:talksTo> ?a . "//
-			+ "  ?dick <uri:talksTo> ?jane . "//
-			+ "  ?jane <uri:talksTo> ?betty . "//
-			+ "}";//
-
-	private final String q14 = ""//
-			+ "SELECT ?harry ?susan ?mary " //
-			+ "{" //
-			+ "  ?harry <uri:talksTo> ?susan . "//
-			+ "  ?susan <uri:talksTo> ?mary . "//
-			+ "}";//
-
-	String q15 = ""//
-			+ "SELECT ?a ?b ?c ?d ?e ?f ?q " //
-			+ "{" //
-			+ " GRAPH ?x { " //
-			+ "  ?a a ?b ."//
-			+ "  ?b <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-			+ "  ?d <uri:talksTo> ?e . "//
-			+ "  FILTER ( ?e < ?f && (?a > ?b || ?c = ?d) ). " //
-			+ "  FILTER(bound(?f) && sameTerm(?a,?b)&&bound(?q)). " //
-			+ "  ?b a ?q ."//
-			+ "		}"//
-			+ "}";//
-
-	String q16 = ""//
-			+ "SELECT ?g ?h ?i " //
-			+ "{" //
-			+ " GRAPH ?y { " //
-			+ "  ?g a ?h ."//
-			+ "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?i ."//
-			+ "		}"//
-			+ "}";//
-
-	String q17 = ""//
-			+ "SELECT ?j ?k ?l ?m ?n ?o " //
-			+ "{" //
-			+ " GRAPH ?z { " //
-			+ "  ?j <uri:talksTo> ?k . "//
-			+ "  FILTER ( ?k < ?l && (?m > ?n || ?o = ?j) ). " //
-			+ "		}"//
-			+ "}";//
-
-	String q18 = ""//
-			+ "SELECT ?r ?s ?t ?u " //
-			+ "{" //
-			+ " GRAPH ?q { " //
-			+ "  FILTER(bound(?r) && sameTerm(?s,?t)&&bound(?u)). " //
-			+ "  ?t a ?u ."//
-			+ "		}"//
-			+ "}";//
-
-	String q19 = ""//
-			+ "SELECT ?a ?b ?c ?d ?e ?f ?q ?g ?h " //
-			+ "{" //
-			+ " GRAPH ?x { " //
-			+ "  ?a a ?b ."//
-			+ "  ?b <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
-			+ "  ?d <uri:talksTo> ?e . "//
-			+ "  FILTER ( ?e < ?f && (?a > ?b || ?c = ?d) ). " //
-			+ "  FILTER(bound(?f) && sameTerm(?a,?b)&&bound(?q)). " //
-			+ "  FILTER(?g IN (1,2,3) && ?h NOT IN(5,6,7)). " //
-			+ "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?g. "//
-			+ "  ?b a ?q ."//
-			+ "		}"//
-			+ "}";//
-
-	String q20 = ""//
-			+ "SELECT ?m ?n " //
-			+ "{" //
-			+ " GRAPH ?q { " //
-			+ "  FILTER(?m IN (1,2,3) && ?n NOT IN(5,6,7)). " //
-			+ "  ?n <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
-			+ "		}"//
-			+ "}";//
-
-	String q21 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
-			+ "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>  "//
-			+ "SELECT ?feature ?point ?wkt " //
-			+ "{" //
-			+ "  ?feature a geo:Feature . "//
-			+ "  ?feature geo:hasGeometry ?point . "//
-			+ "  ?point a geo:Point . "//
-			+ "  ?point geo:asWKT ?wkt . "//
-			+ "  FILTER(geof:sfWithin(?wkt, \"Polygon\")) " //
-			+ "}";//
-
-	String q22 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "SELECT ?person ?commentmatch ?labelmatch" //
-			+ "{" //
-			+ "  ?person a <http://example.org/ontology/Person> . "//
-			+ "  ?person <http://www.w3.org/2000/01/rdf-schema#label> ?labelmatch . "//
-			+ "  ?person <http://www.w3.org/2000/01/rdf-schema#comment> ?commentmatch . "//
-			+ "  FILTER(fts:text(?labelmatch, \"bob\")) . " //
-			+ "  FILTER(fts:text(?commentmatch, \"bob\"))  " //
-			+ "}";//
-
-	String q23 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
-			+ "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>  "//
-			+ "SELECT ?a ?b ?c " //
-			+ "{" //
-			+ "  ?a a geo:Feature . "//
-			+ "  ?b a geo:Point . "//
-			+ "  ?b geo:asWKT ?c . "//
-			+ "  FILTER(geof:sfWithin(?c, \"Polygon\")) " //
-			+ "}";//
-
-	String q24 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "SELECT ?f ?g " //
-			+ "{" //
-			+ "  ?f <http://www.w3.org/2000/01/rdf-schema#comment> ?g . "//
-			+ "  FILTER(fts:text(?g, \"bob\"))  " //
-			+ "}";//
-
-	String q25 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "SELECT ?person ?commentmatch ?labelmatch ?point" //
-			+ "{" //
-			+ "  ?person a ?point. " //
-			+ "  ?person a <http://example.org/ontology/Person> . "//
-			+ "  ?person <http://www.w3.org/2000/01/rdf-schema#label> ?labelmatch . "//
-			+ "  ?person <http://www.w3.org/2000/01/rdf-schema#comment> ?commentmatch . "//
-			+ "  FILTER((?person > ?point) || (?person = ?labelmatch)). "
-			+ "  FILTER(fts:text(?labelmatch, \"bob\")) . " //
-			+ "  FILTER(fts:text(?commentmatch, \"bob\"))  " //
-			+ "}";//
-
-	String q26 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "SELECT ?a ?b ?c  " //
-			+ "{" //
-			+ "  ?a a ?c. " //
-			+ "  ?a a <http://example.org/ontology/Person> . "//
-			+ "  ?a <http://www.w3.org/2000/01/rdf-schema#label> ?b . "//
-			+ "  FILTER((?a > ?c) || (?a = ?b)). "
-			+ "  FILTER(fts:text(?b, \"bob\")) . " //
-			+ "}";//
-
-	String q27 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
-			+ "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>  "//
-			+ "SELECT ?person ?commentmatch ?labelmatch ?other ?feature ?point ?wkt ?g ?h" //
-			+ "{" //
-			+ "  ?person a <http://example.org/ontology/Person> . "//
-			+ "  ?person <http://www.w3.org/2000/01/rdf-schema#label> ?labelmatch . "//
-			+ "  ?person <http://www.w3.org/2000/01/rdf-schema#comment> ?commentmatch . "//
-			+ "  FILTER((?person > ?other) || (?person = ?labelmatch)). "
-			+ "  ?person a ?other. "//
-			+ "  FILTER(fts:text(?labelmatch, \"bob\")) . " //
-			+ "  FILTER(fts:text(?commentmatch, \"bob\"))  " //
-			+ " ?feature a geo:Feature . "//
-			+ "  ?point a geo:Point . "//
-			+ "  ?point geo:asWKT ?wkt . "//
-			+ "  FILTER(geof:sfWithin(?wkt, \"Polygon\")) " //
-			+ "  FILTER(?g IN (1,2,3) && ?h NOT IN(5,6,7)). " //
-			+ "  ?h <http://www.w3.org/2000/01/rdf-schema#label> ?g. "//
-			+ "}";//
-
-	String q28 = ""//
-			+ "SELECT ?m ?n " //
-			+ "{" //
-			+ "  FILTER(?m IN (1,2,3) && ?n NOT IN(5,6,7)). " //
-			+ "  ?n <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
-			+ "}";//
-
-	String q29 = ""//
-			+ "SELECT ?m ?n ?o" //
-			+ "{" //
-			+ "  FILTER(?m IN (1,2,3) && ?n NOT IN(5,6,7)). " //
-			+ "  ?n <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
-			+ "  ?m a ?o." //
-			+ "  FILTER(ISNUMERIC(?o))." + "}";//
-
-	String q30 = ""//
-			+ "SELECT ?pig ?dog ?owl" //
-			+ "{" //
-			+ "  FILTER(?pig IN (1,2,3) && ?dog NOT IN(5,6,7)). " //
-			+ "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?pig. "//
-			+ "  ?pig a ?owl. " //
-			+ "  FILTER(ISNUMERIC(?owl))." + "}";//
-
-	String q31 = ""//
-			+ "SELECT ?q ?r ?s " //
-			+ "{" //
-			+ "  {?q a ?r} UNION {?r a ?s} ."//
-			+ "  ?r a ?s ."//
-			+ "}";//
-
-	String q33 = ""//
-			+ "SELECT ?q ?r ?s ?t " //
-			+ "{" //
-			+ "  OPTIONAL {?q a ?r} ."//
-			+ "  ?s a ?t ."//
-			+ "}";//
-
-	String q34 = ""//
-			+ "SELECT ?q ?r  " //
-			+ "{" //
-			+ "  FILTER(?q > ?r) ."//
-			+ "  ?q a ?r ."//
-			+ "}";//
-
-	String q35 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "SELECT ?s ?t ?u ?v ?w ?x ?y ?z " //
-			+ "{" //
-			+ "  FILTER(?s > ?t)."//
-			+ "  ?s a ?t ."//
-			+ "  FILTER(?u > ?v)."//
-			+ "  ?u a ?v ."//
-			+ "  ?w <http://www.w3.org/2000/01/rdf-schema#label> ?x ."//
-			+ "  FILTER(fts:text(?x, \"bob\")) . " //
-			+ "  ?y <http://www.w3.org/2000/01/rdf-schema#label> ?z ."//
-			+ "  FILTER(fts:text(?z, \"bob\")) . " //
-			+ "}";//
-
-	String q36 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "SELECT ?dog ?cat  " //
-			+ "{" //
-			+ "  ?dog <http://www.w3.org/2000/01/rdf-schema#label> ?cat ."//
-			+ "  FILTER(fts:text(?cat, \"bob\")) . " //
-			+ "}";//
-
-	String q37 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "SELECT ?s ?t " //
-			+ "{" //
-			+ "  FILTER(?s > ?t)."//
-			+ "  ?s a ?t ."//
-			+ "  FILTER(?s > ?t)."//
-			+ "  ?s a ?t ."//
-			+ "  FILTER(?s > ?t)."//
-			+ "  ?s a ?t ."//
-			+ "}";//
-
-	String q38 = "PREFIX fts: <http://rdf.useekm.com/fts#>  "//
-			+ "SELECT ?s ?t " //
-			+ "{" //
-			+ "  FILTER(?s > ?t)."//
-			+ "  ?s a ?t ."//
-			+ "  ?t <http://www.w3.org/2000/01/rdf-schema#label> ?s ."//
-			+ "  FILTER(?s > ?t)."//
-			+ "}";//
-
-	String q39 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
-			+ "SELECT ?s ?t " //
-			+ "{" //
-			+ " VALUES(?s) { (<ub:poodle>)(<ub:pitbull>)} ." //
-			+ " ?t <ub:peesOn> <ub:rug> ." //
-			+ " ?t <http://www.w3.org/2000/01/rdf-schema#label> ?s ."//
-			+ "}";//
-
-	String q40 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
-			+ "SELECT ?u ?v " //
-			+ "{" //
-			+ " ?v <ub:peesOn> <ub:rug> ." //
-			+ " ?v <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-			+ "}";//
-
-	String q41 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
-			+ "SELECT ?s ?t ?w ?x" //
-			+ "{" //
-			+ " FILTER(?s > ?t)."//
-			+ " VALUES(?s) { (<ub:poodle>)(<ub:pitbull>)} ." //
-			+ " VALUES(?w) { (<ub:persian>) (<ub:siamese>) } ." //
-			+ " ?t <ub:peesOn> <ub:rug> ." //
-			+ " ?t <http://www.w3.org/2000/01/rdf-schema#label> ?s ."//
-			+ " ?w <ub:peesOn> <ub:rug> ." //
-			+ " ?w <http://www.w3.org/2000/01/rdf-schema#label> ?x ."//
-			+ "}";//
-
-	String q42 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
-			+ "SELECT ?u ?v " //
-			+ "{" //
-			+ " FILTER(?u > ?v)."//
-			+ " ?v <ub:peesOn> <ub:rug> ." //
-			+ " ?v <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
-			+ "}";//
-
-	String q43 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
-			+ "SELECT ?a ?b " //
-			+ "{" //
-			+ " ?b <ub:peesOn> <ub:rug> ." //
-			+ " ?b <http://www.w3.org/2000/01/rdf-schema#label> ?a ."//
-			+ "}";//
-
-	@Test
-	public void testVarRelableIndexSmaller() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(queryString, null);
-		final ParsedQuery pq2 = parser2.parseQuery(indexSparqlString, null);
-
-		System.out.println("Query is " + pq1.getTupleExpr());
-		System.out.println("Index is " + pq2.getTupleExpr());
-
-		final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup);
-
-		final TupleExpr tup = pq1.getTupleExpr().clone();
-		final PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		final Set<StatementPattern> qSet = Sets
-				.newHashSet(StatementPatternCollector.process(pq1
-						.getTupleExpr()));
-		final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		final Set<StatementPattern> set = Sets.newHashSet();
-		for (final QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(qSet.containsAll(set) && set.size() != 0);
-	}
-
-	@Test
-	public void testVarRelableIndexSameSize() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q1, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q2, null);
-
-		final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup);
-
-		final TupleExpr tup = pq1.getTupleExpr().clone();
-		final PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		final Set<StatementPattern> qSet = Sets
-				.newHashSet(StatementPatternCollector.process(pq1
-						.getTupleExpr()));
-		final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		final Set<StatementPattern> set = Sets.newHashSet();
-		for (final QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(set.equals(qSet));
-
-	}
-
-	@Test
-	public void testTwoIndexLargeQuery() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-		final SPARQLParser parser3 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q11, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q7, null);
-		final ParsedQuery pq3 = parser3.parseQuery(q12, null);
-
-		System.out.println("Query is " + pq1.getTupleExpr());
-		System.out.println("Indexes are " + pq2.getTupleExpr() + " and "
-				+ pq3.getTupleExpr());
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				(Projection) pq3.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup1);
-		list.add(extTup2);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(set.equals(qSet));
-
-	}
-
-	@Test
-	public void testThreeIndexLargeQuery() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-		final SPARQLParser parser3 = new SPARQLParser();
-		final SPARQLParser parser4 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q13, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q5, null);
-		final ParsedQuery pq3 = parser3.parseQuery(q12, null);
-		final ParsedQuery pq4 = parser4.parseQuery(q14, null);
-
-		System.out.println("Query is " + pq1.getTupleExpr());
-		System.out.println("Indexes are " + pq2.getTupleExpr() + " , "
-				+ pq3.getTupleExpr() + " , " + pq4.getTupleExpr());
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				(Projection) pq3.getTupleExpr());
-		final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				(Projection) pq4.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup1);
-		list.add(extTup2);
-		list.add(extTup3);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(set.equals(qSet));
-
-	}
-
-	@Test
-	public void testSingleIndexLargeQuery() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q8, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q7, null);
-
-		final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(set.equals(qSet));
-
-	}
-
-	@Test
-	public void testContextFilter1() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-		final SPARQLParser parser3 = new SPARQLParser();
-		final SPARQLParser parser4 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q15, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q16, null);
-		final ParsedQuery pq3 = parser3.parseQuery(q17, null);
-		final ParsedQuery pq4 = parser4.parseQuery(q18, null);
-
-		System.out.println("Query is " + pq1.getTupleExpr());
-		System.out.println("Indexes are " + pq2.getTupleExpr() + " , "
-				+ pq3.getTupleExpr() + " , " + pq4.getTupleExpr());
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				(Projection) pq3.getTupleExpr());
-		final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				(Projection) pq4.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup1);
-		list.add(extTup2);
-		list.add(extTup3);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(qSet.containsAll(set));
-		Assert.assertEquals(3, eTupSet.size());
-	}
-
-	@Test
-	public void testGeoFilter() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-
-		String query1 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
-				+ "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>  "//
-				+ "SELECT ?a ?b ?c " //
-				+ "{" //
-				+ "  ?a a geo:Feature . "//
-				+ "  ?b a geo:Point . "//
-				+ "  ?b geo:asWKT ?c . "//
-				+ "  FILTER(geof:sfWithin(?b, \"Polygon\")) " //
-				+ "}";//
-
-		String query2 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
-				+ "SELECT ?f ?g " //
-				+ "{" //
-				+ "  ?f a geo:Feature . "//
-				+ "  ?g a geo:Point . "//
-				+ "}";//
-
-		final ParsedQuery pq1 = parser1.parseQuery(query1, null);
-		final ParsedQuery pq2 = parser2.parseQuery(query2, null);
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup1);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(qSet.containsAll(set) && eTupSet.size() == 1);
-	}
-
-	@Test
-	public void testContextFilter2() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-
-		String query1 = ""//
-				+ "SELECT ?k ?l ?m ?n " //
-				+ "{" //
-				+ " GRAPH ?z { " //
-				+ " ?l <uri:talksTo> ?n . "//
-				+ " ?l a ?n."//
-				+ " ?k a ?m."//
-				+ "  FILTER ((?k < ?l) && (?m < ?n)). " //
-				+ "		}"//
-				+ "}";//
-
-		String query2 = ""//
-				+ "SELECT ?s ?t " //
-				+ "{" //
-				+ " GRAPH ?r { " //
-				+ " ?s <uri:talksTo> ?t . "//
-				+ " ?s a ?t."//
-				+ "	}"//
-				+ "}";//
-
-		final ParsedQuery pq1 = parser1.parseQuery(query1, null);
-		final ParsedQuery pq2 = parser2.parseQuery(query2, null);
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup1);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(qSet.containsAll(set) && eTupSet.size() == 1);
-	}
-
-	@Test
-	public void testGeoIndexFunction() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q21, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q23, null);
-
-		System.out.println("Query is " + pq1.getTupleExpr());
-		System.out.println("Index is " + pq2.getTupleExpr());
-
-		final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(qSet.containsAll(set) && set.size() != 0);
-
-	}
-
-	@Test
-	public void testFreeTextIndexFunction() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q22, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q24, null);
-
-		System.out.println("Query is " + pq1.getTupleExpr());
-		System.out.println("Index is " + pq2.getTupleExpr());
-
-		final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
-				(Projection) pq2.getTupleExpr());
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
-
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
-
-		Assert.assertTrue(qSet.containsAll(set) && set.size() != 0);
-
-	}
-
-	@Test
-	public void testThreeIndexGeoFreeCompareFilterMix() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-		final SPARQLParser parser3 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q25, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q24, null);
-		final ParsedQuery pq3 = parser3.parseQuery(q26, null);
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				new Projection(pq3.getTupleExpr()));
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup1);
-		list.add(extTup2);
-
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
-
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
+        System.out.println("Query is " + pq1.getTupleExpr());
+        System.out.println("Indexes are " + pq2.getTupleExpr() + " and "
+                + pq3.getTupleExpr());
 
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                (Projection) pq3.getTupleExpr());
 
-		Assert.assertTrue(set.equals(qSet) && eTupSet.size() == 2);
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup1);
+        list.add(extTup2);
 
-	}
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
 
-	@Test
-	public void testFourIndexGeoFreeCompareFilterMix() throws Exception {
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
 
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-		final SPARQLParser parser3 = new SPARQLParser();
-		final SPARQLParser parser4 = new SPARQLParser();
-		final SPARQLParser parser5 = new SPARQLParser();
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
 
-		final ParsedQuery pq1 = parser1.parseQuery(q27, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q23, null);
-		final ParsedQuery pq3 = parser3.parseQuery(q26, null);
-		final ParsedQuery pq4 = parser4.parseQuery(q24, null);
-		final ParsedQuery pq5 = parser5.parseQuery(q28, null);
+        Assert.assertTrue(set.equals(qSet));
 
-		System.out.println("Query is " + pq1.getTupleExpr());
-		System.out.println("Indexes are " + pq2.getTupleExpr() + " , "
-				+ pq3.getTupleExpr() + " , " + pq4.getTupleExpr() + " and "
-				+ pq5.getTupleExpr());
+    }
 
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				new Projection(pq3.getTupleExpr()));
-		final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				new Projection(pq4.getTupleExpr()));
-		final SimpleExternalTupleSet extTup4 = new SimpleExternalTupleSet(
-				new Projection(pq5.getTupleExpr()));
+    @Test
+    public void testThreeIndexLargeQuery() throws Exception {
 
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup4);
-		list.add(extTup1);
-		list.add(extTup2);
-		list.add(extTup3);
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+        final SPARQLParser parser3 = new SPARQLParser();
+        final SPARQLParser parser4 = new SPARQLParser();
 
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
+        final ParsedQuery pq1 = parser1.parseQuery(q13, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q5, null);
+        final ParsedQuery pq3 = parser3.parseQuery(q12, null);
+        final ParsedQuery pq4 = parser4.parseQuery(q14, null);
 
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
+        System.out.println("Query is " + pq1.getTupleExpr());
+        System.out.println("Indexes are " + pq2.getTupleExpr() + " , "
+                + pq3.getTupleExpr() + " , " + pq4.getTupleExpr());
 
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                (Projection) pq3.getTupleExpr());
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                (Projection) pq4.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup1);
+        list.add(extTup2);
+        list.add(extTup3);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(set.equals(qSet));
+
+    }
+
+    @Test
+    public void testSingleIndexLargeQuery() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q8, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q7, null);
+
+        final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(set.equals(qSet));
+
+    }
+
+    @Test
+    public void testContextFilter1() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+        final SPARQLParser parser3 = new SPARQLParser();
+        final SPARQLParser parser4 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q15, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q16, null);
+        final ParsedQuery pq3 = parser3.parseQuery(q17, null);
+        final ParsedQuery pq4 = parser4.parseQuery(q18, null);
+
+        System.out.println("Query is " + pq1.getTupleExpr());
+        System.out.println("Indexes are " + pq2.getTupleExpr() + " , "
+                + pq3.getTupleExpr() + " , " + pq4.getTupleExpr());
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                (Projection) pq3.getTupleExpr());
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                (Projection) pq4.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup1);
+        list.add(extTup2);
+        list.add(extTup3);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(qSet.containsAll(set));
+        Assert.assertEquals(3, eTupSet.size());
+    }
+
+    @Test
+    public void testGeoFilter() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+
+        final String query1 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
+                + "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>  "//
+                + "SELECT ?a ?b ?c " //
+                + "{" //
+                + "  ?a a geo:Feature . "//
+                + "  ?b a geo:Point . "//
+                + "  ?b geo:asWKT ?c . "//
+                + "  FILTER(geof:sfWithin(?b, \"Polygon\")) " //
+                + "}";//
+
+        final String query2 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#>  "//
+                + "SELECT ?f ?g " //
+                + "{" //
+                + "  ?f a geo:Feature . "//
+                + "  ?g a geo:Point . "//
+                + "}";//
+
+        final ParsedQuery pq1 = parser1.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser2.parseQuery(query2, null);
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup1);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(qSet.containsAll(set) && eTupSet.size() == 1);
+    }
+
+    @Test
+    public void testContextFilter2() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+
+        final String query1 = ""//
+                + "SELECT ?k ?l ?m ?n " //
+                + "{" //
+                + " GRAPH ?z { " //
+                + " ?l <uri:talksTo> ?n . "//
+                + " ?l a ?n."//
+                + " ?k a ?m."//
+                + "  FILTER ((?k < ?l) && (?m < ?n)). " //
+                + "		}"//
+                + "}";//
+
+        final String query2 = ""//
+                + "SELECT ?s ?t " //
+                + "{" //
+                + " GRAPH ?r { " //
+                + " ?s <uri:talksTo> ?t . "//
+                + " ?s a ?t."//
+                + "	}"//
+                + "}";//
+
+        final ParsedQuery pq1 = parser1.parseQuery(query1, null);
+        final ParsedQuery pq2 = parser2.parseQuery(query2, null);
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup1);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(qSet.containsAll(set) && eTupSet.size() == 1);
+    }
+
+    @Test
+    public void testGeoIndexFunction() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q21, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q23, null);
+
+        System.out.println("Query is " + pq1.getTupleExpr());
+        System.out.println("Index is " + pq2.getTupleExpr());
+
+        final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
 
-		Assert.assertTrue(set.equals(qSet));
-
-	}
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup);
 
-	@Test
-	public void testThreeIndexGeoFreeCompareFilterMix2() throws Exception {
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
 
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-		final SPARQLParser parser3 = new SPARQLParser();
-		final SPARQLParser parser4 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q27, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q23, null);
-		final ParsedQuery pq3 = parser3.parseQuery(q26, null);
-		final ParsedQuery pq4 = parser4.parseQuery(q28, null);
-
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				new Projection(pq3.getTupleExpr()));
-		final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
-				new Projection(pq4.getTupleExpr()));
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-
-		list.add(extTup1);
-		list.add(extTup3);
-		list.add(extTup2);
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(qSet.containsAll(set) && set.size() != 0);
 
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
+    }
+
+    @Test
+    public void testFreeTextIndexFunction() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q22, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q24, null);
+
+        System.out.println("Query is " + pq1.getTupleExpr());
+        System.out.println("Index is " + pq2.getTupleExpr());
+
+        final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
+                (Projection) pq2.getTupleExpr());
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
 
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
+        Assert.assertTrue(qSet.containsAll(set) && set.size() != 0);
 
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
+    }
 
-		Assert.assertTrue(qSet.containsAll(set));
+    @Test
+    public void testThreeIndexGeoFreeCompareFilterMix() throws Exception {
 
-	}
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+        final SPARQLParser parser3 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q25, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q24, null);
+        final ParsedQuery pq3 = parser3.parseQuery(q26, null);
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                new Projection(pq3.getTupleExpr()));
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup1);
+        list.add(extTup2);
 
-	@Test
-	public void testISNUMERIC() throws Exception {
-
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-
-		final ParsedQuery pq1 = parser1.parseQuery(q29, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q30, null);
-
-		final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup);
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(set.equals(qSet) && eTupSet.size() == 2);
+
+    }
+
+    @Test
+    public void testFourIndexGeoFreeCompareFilterMix() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+        final SPARQLParser parser3 = new SPARQLParser();
+        final SPARQLParser parser4 = new SPARQLParser();
+        final SPARQLParser parser5 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q27, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q23, null);
+        final ParsedQuery pq3 = parser3.parseQuery(q26, null);
+        final ParsedQuery pq4 = parser4.parseQuery(q24, null);
+        final ParsedQuery pq5 = parser5.parseQuery(q28, null);
 
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
+        System.out.println("Query is " + pq1.getTupleExpr());
+        System.out.println("Indexes are " + pq2.getTupleExpr() + " , "
+                + pq3.getTupleExpr() + " , " + pq4.getTupleExpr() + " and "
+                + pq5.getTupleExpr());
 
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                new Projection(pq3.getTupleExpr()));
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                new Projection(pq4.getTupleExpr()));
+        final SimpleExternalTupleSet extTup4 = new SimpleExternalTupleSet(
+                new Projection(pq5.getTupleExpr()));
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup4);
+        list.add(extTup1);
+        list.add(extTup2);
+        list.add(extTup3);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(set.equals(qSet));
+
+    }
+
+    @Test
+    public void testThreeIndexGeoFreeCompareFilterMix2() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+        final SPARQLParser parser3 = new SPARQLParser();
+        final SPARQLParser parser4 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q27, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q23, null);
+        final ParsedQuery pq3 = parser3.parseQuery(q26, null);
+        final ParsedQuery pq4 = parser4.parseQuery(q28, null);
+
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                new Projection(pq3.getTupleExpr()));
+        final SimpleExternalTupleSet extTup3 = new SimpleExternalTupleSet(
+                new Projection(pq4.getTupleExpr()));
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+
+        list.add(extTup1);
+        list.add(extTup3);
+        list.add(extTup2);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
+
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
+
+        Assert.assertTrue(qSet.containsAll(set));
+
+    }
+
+    @Test
+    public void testISNUMERIC() throws Exception {
+
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+
+        final ParsedQuery pq1 = parser1.parseQuery(q29, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q30, null);
+
+        final SimpleExternalTupleSet extTup = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup);
+
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
+
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
 
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
 
-		Assert.assertTrue(set.equals(qSet) && eTupSet.size() == 1);
+        Assert.assertTrue(set.equals(qSet) && eTupSet.size() == 1);
 
-	}
+    }
 
-	@Test
-	public void testTwoRepeatedIndex() throws Exception {
+    @Test
+    public void testTwoRepeatedIndex() throws Exception {
 
-		final SPARQLParser parser1 = new SPARQLParser();
-		final SPARQLParser parser2 = new SPARQLParser();
-		final SPARQLParser parser3 = new SPARQLParser();
+        final SPARQLParser parser1 = new SPARQLParser();
+        final SPARQLParser parser2 = new SPARQLParser();
+        final SPARQLParser parser3 = new SPARQLParser();
 
-		final ParsedQuery pq1 = parser1.parseQuery(q35, null);
-		final ParsedQuery pq2 = parser2.parseQuery(q34, null);
-		final ParsedQuery pq3 = parser3.parseQuery(q36, null);
+        final ParsedQuery pq1 = parser1.parseQuery(q35, null);
+        final ParsedQuery pq2 = parser2.parseQuery(q34, null);
+        final ParsedQuery pq3 = parser3.parseQuery(q36, null);
 
-		System.out.println("Query is " + pq1.getTupleExpr());
-		System.out.println("Indexes are " + pq2.getTupleExpr() + " and "
-				+ pq3.getTupleExpr());
+        System.out.println("Query is " + pq1.getTupleExpr());
+        System.out.println("Indexes are " + pq2.getTupleExpr() + " and "
+                + pq3.getTupleExpr());
 
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				new Projection(pq3.getTupleExpr()));
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                new Projection(pq3.getTupleExpr()));
 
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup1);
-		list.add(extTup2);
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup1);
+        list.add(extTup2);
 
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
 
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
 
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
 
-		Assert.assertEquals(4, eTupSet.size());
-		Assert.assertEquals(qSet, set);
+        Assert.assertEquals(4, eTupSet.size());
+        Assert.assertEquals(qSet, set);
 
-	}
+    }
 
-	@Test
-	public void testBindingSetAssignment2() throws Exception {
+    @Test
+    public void testBindingSetAssignment2() throws Exception {
 
-		final SPARQLParser parser = new SPARQLParser();
+        final SPARQLParser parser = new SPARQLParser();
 
-		final ParsedQuery pq1 = parser.parseQuery(q41, null);
-		final ParsedQuery pq2 = parser.parseQuery(q42, null);
-		final ParsedQuery pq3 = parser.parseQuery(q43, null);
+        final ParsedQuery pq1 = parser.parseQuery(q41, null);
+        final ParsedQuery pq2 = parser.parseQuery(q42, null);
+        final ParsedQuery pq3 = parser.parseQuery(q43, null);
 
-		final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
-				new Projection(pq2.getTupleExpr()));
-		final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
-				new Projection(pq3.getTupleExpr()));
+        final SimpleExternalTupleSet extTup1 = new SimpleExternalTupleSet(
+                new Projection(pq2.getTupleExpr()));
+        final SimpleExternalTupleSet extTup2 = new SimpleExternalTupleSet(
+                new Projection(pq3.getTupleExpr()));
 
-		final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
-		list.add(extTup1);
-		list.add(extTup2);
+        final List<ExternalTupleSet> list = new ArrayList<ExternalTupleSet>();
+        list.add(extTup1);
+        list.add(extTup2);
 
-		TupleExpr tup = pq1.getTupleExpr().clone();
-		PCJOptimizer pcj = new PCJOptimizer(list, false);
-		pcj.optimize(tup, null, null);
+        final TupleExpr tup = pq1.getTupleExpr().clone();
+        provider.setIndices(list);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, provider);
+        pcj.optimize(tup, null, null);
 
-		Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
-				.process(pq1.getTupleExpr()));
-		Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
-				.getTupleSets(tup);
+        final Set<StatementPattern> qSet = Sets.newHashSet(StatementPatternCollector
+                .process(pq1.getTupleExpr()));
+        final Set<QueryModelNode> eTupSet = PcjIntegrationTestingUtil
+                .getTupleSets(tup);
 
-		Set<StatementPattern> set = Sets.newHashSet();
-		for (QueryModelNode s : eTupSet) {
-			set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
-					.getTupleExpr()));
-		}
+        final Set<StatementPattern> set = Sets.newHashSet();
+        for (final QueryModelNode s : eTupSet) {
+            set.addAll(StatementPatternCollector.process(((ExternalTupleSet) s)
+                    .getTupleExpr()));
+        }
 
-		Assert.assertEquals(2, eTupSet.size());
-		Assert.assertEquals(qSet, set);
+        Assert.assertEquals(2, eTupSet.size());
+        Assert.assertEquals(qSet, set);
 
-		BindingSetAssignmentCollector bsac1 = new BindingSetAssignmentCollector();
-		BindingSetAssignmentCollector bsac2 = new BindingSetAssignmentCollector();
-		pq1.getTupleExpr().visit(bsac1);
-		tup.visit(bsac2);
+        final BindingSetAssignmentCollector bsac1 = new BindingSetAssignmentCollector();
+        final BindingSetAssignmentCollector bsac2 = new BindingSetAssignmentCollector();
+        pq1.getTupleExpr().visit(bsac1);
+        tup.visit(bsac2);
 
-		Assert.assertEquals(bsac1.getBindingSetAssignments(),
-				bsac2.getBindingSetAssignments());
+        Assert.assertEquals(bsac1.getBindingSetAssignments(),
+                bsac2.getBindingSetAssignments());
 
-	}
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/c826ffea/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerVarToConstTest.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerVarToConstTest.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerVarToConstTest.java
index 1b9b408..b3823de 100644
--- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerVarToConstTest.java
+++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/PrecompJoinOptimizerVarToConstTest.java
@@ -24,10 +24,11 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
 import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
 import org.apache.rya.indexing.pcj.matching.PCJOptimizer;
-
+import org.apache.rya.indexing.pcj.matching.provider.AccumuloIndexSetProvider;
 import org.junit.Assert;
 import org.junit.Test;
 import org.openrdf.query.algebra.Projection;
@@ -224,7 +225,7 @@ public class PrecompJoinOptimizerVarToConstTest {
 
         final TupleExpr tup = pq1.getTupleExpr().clone();
 
-		final PCJOptimizer pcj = new PCJOptimizer(list, false);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, new AccumuloIndexSetProvider(new Configuration(), list));
         pcj.optimize(tup, null, null);
 
         System.out.println("Processed query is " + tup);
@@ -264,7 +265,7 @@ public class PrecompJoinOptimizerVarToConstTest {
         list.add(extTup);
 
         final TupleExpr tup = pq1.getTupleExpr().clone();
-		final PCJOptimizer pcj = new PCJOptimizer(list, false);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, new AccumuloIndexSetProvider(new Configuration(), list));
         pcj.optimize(tup, null, null);
 
         System.out.println("Processed query is " + tup);
@@ -305,7 +306,7 @@ public class PrecompJoinOptimizerVarToConstTest {
         list.add(extTup);
 
         final TupleExpr tup = pq1.getTupleExpr().clone();
-		final PCJOptimizer pcj = new PCJOptimizer(list, false);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, new AccumuloIndexSetProvider(new Configuration(), list));
         pcj.optimize(tup, null, null);
 
         System.out.println("Processed query is " + tup);
@@ -350,7 +351,7 @@ public class PrecompJoinOptimizerVarToConstTest {
         list.add(extTup2);
 
         final TupleExpr tup = pq1.getTupleExpr().clone();
-		final PCJOptimizer pcj = new PCJOptimizer(list, false);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, new AccumuloIndexSetProvider(new Configuration(), list));
         pcj.optimize(tup, null, null);
 
         System.out.println("Processed query is " + tup);
@@ -399,7 +400,7 @@ public class PrecompJoinOptimizerVarToConstTest {
         list.add(extTup3);
 
         final TupleExpr tup = pq1.getTupleExpr().clone();
-		final PCJOptimizer pcj = new PCJOptimizer(list, false);
+        final PCJOptimizer pcj = new PCJOptimizer(list, false, new AccumuloIndexSetProvider(new Configuration(), list));
         pcj.optimize(tup, null, null);
 
         System.out.println("Processed query is " + tup);