/*
 * 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.accumulo;

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.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.BatchWriter;
import org.apache.accumulo.core.client.BatchWriterConfig;
import org.apache.accumulo.core.client.ConditionalWriter;
import org.apache.accumulo.core.client.ConditionalWriterConfig;
import org.apache.accumulo.core.client.Connector;
import org.apache.accumulo.core.client.MutationsRejectedException;
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.admin.TableOperations;
import org.apache.accumulo.core.client.lexicoder.ListLexicoder;
import org.apache.accumulo.core.client.lexicoder.LongLexicoder;
import org.apache.accumulo.core.client.lexicoder.StringLexicoder;
import org.apache.accumulo.core.client.mock.MockInstance;
import org.apache.accumulo.core.data.Condition;
import org.apache.accumulo.core.data.ConditionalMutation;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Mutation;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.accumulo.core.security.ColumnVisibility;
import org.apache.hadoop.io.Text;
import org.apache.log4j.Logger;
import org.apache.rya.api.model.VisibilityBindingSet;
import org.apache.rya.indexing.pcj.storage.PcjMetadata;
import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.CloseableIterator;
import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException;
import org.apache.rya.indexing.pcj.storage.accumulo.BindingSetConverter.BindingSetConversionException;
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.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;

import com.google.common.base.Optional;

import edu.umd.cs.findbugs.annotations.DefaultAnnotation;
import edu.umd.cs.findbugs.annotations.NonNull;

/**
 * Functions that create and maintain the PCJ tables that are used by Rya.
 */
@DefaultAnnotation(NonNull.class)
public class PcjTables {
    private static final Logger log = Logger.getLogger(PcjTables.class);

    /**
     * The Row ID of all {@link PcjMetadata} entries that are stored in Accumulo.
     */
    private static final Text PCJ_METADATA_ROW_ID = new Text("pcjMetadata");

    /**
     * The Column Family for all PCJ metadata entries.
     */
    private static final Text PCJ_METADATA_FAMILY = new Text("metadata");

    /**
     * The Column Qualifier for the SPARQL query a PCJ is built from.
     */
    private static final Text PCJ_METADATA_SPARQL_QUERY = new Text("sparql");

    /**
     * The Column Qualifier for the cardinality of a PCJ.
     */
    private static final Text PCJ_METADATA_CARDINALITY = new Text("cardinality");

    /**
     * The Column Qualifier for the various variable orders a PCJ's results are written to.
     */
    private static final Text PCJ_METADATA_VARIABLE_ORDERS = new Text("variableOrders");

    // Lexicoders used to read/write PcjMetadata to/from Accumulo.
    private static final LongLexicoder longLexicoder = new LongLexicoder();
    private static final StringLexicoder stringLexicoder = new StringLexicoder();
    private static final ListLexicoder<String> listLexicoder = new ListLexicoder<>(stringLexicoder);

    /**
     * Create a new PCJ table within an Accumulo instance for a SPARQL query.
     * For example, calling the function like this:
     * <pre>
     * PcjTables.createPcjTable(
     *     accumuloConn,
     *
     *     "foo_INDEX_query1234",
     *
     *     Sets.newHashSet(
     *         new VariableOrder("city;worker;customer"),
     *         new VariableOrder("worker;customer;city") ,
     *         new VariableOrder("customer;city;worker")),
     *
     *     "SELECT ?customer ?worker ?city { " +
     *            "?customer &lt;http://talksTo> ?worker. " +
     *            "?worker &lt;http://livesIn> ?city. " +
     *            "?worker &lt;http://worksAt> &lt;http://Home>. " +
     *     "}");
     * </pre>
     * </p>
     * Will result in an Accumulo table named "foo_INDEX_query1234" with the following entries:
     * <table border="1" style="width:100%">
     *   <tr> <th>Row ID</td>  <th>Column</td>  <th>Value</td> </tr>
     *   <tr> <td>pcjMetadata</td> <td>metadata:sparql</td> <td> ... UTF-8 bytes encoding the query string ... </td> </tr>
     *   <tr> <td>pcjMetadata</td> <td>metadata:cardinality</td> <td> The query's cardinality </td> </tr>
     *   <tr> <td>pcjMetadata</td> <td>metadata:variableOrders</td> <td> The variable orders the results are written to </td> </tr>
     * </table>
     *
     * @param accumuloConn - A connection to the Accumulo that hosts the PCJ table. (not null)
     * @param pcjTableName - The name of the table that will be created. (not null)
     * @param varOrders - The variable orders the results within the table will be written to. (not null)
     * @param sparql - The query this table's results solves. (not null)
     * @throws PCJStorageException Could not create a new PCJ table either because Accumulo
     *   would not let us create it or the PCJ metadata was not able to be written to it.
     */
    public void createPcjTable(
            final Connector accumuloConn,
            final String pcjTableName,
            final Set<VariableOrder> varOrders,
            final String sparql) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);
        checkNotNull(varOrders);
        checkNotNull(sparql);

        final TableOperations tableOps = accumuloConn.tableOperations();
        if(!tableOps.exists(pcjTableName)) {
            BatchWriter writer = null;
            try {
                // Create the new table in Accumulo.
                tableOps.create(pcjTableName);

                // Write the PCJ Metadata to the newly created table.
                final PcjMetadata pcjMetadata = new PcjMetadata(sparql, 0L, varOrders);
                final List<Mutation> mutations = makeWriteMetadataMutations(pcjMetadata);

                writer = accumuloConn.createBatchWriter(pcjTableName, new BatchWriterConfig());
                writer.addMutations(mutations);
            } catch (final TableExistsException e) {
                log.warn("Something else just created the Rya PCJ export table named '" + pcjTableName
                        + "'. This is unexpected, but we will continue as normal.");
            } catch (AccumuloException | AccumuloSecurityException | TableNotFoundException e) {
                throw new PCJStorageException("Could not create a new PCJ named: " + pcjTableName, e);
            } finally {
                if(writer != null) {
                    try {
                        writer.close();
                    } catch (final MutationsRejectedException e) {
                        log.error("Mutations rejected while creating the PCJ table.", e);
                    }
                }
            }
        }
    }

    /**
     * Create the {@link Mutation}s required to write a {@link PCJMetadata} object
     * to an Accumulo table.
     *
     * @param metadata - The metadata to write. (not null)
     * @return An ordered list of mutations that write the metadata to an Accumulo table.
     */
    private static List<Mutation> makeWriteMetadataMutations(final PcjMetadata metadata) {
        checkNotNull(metadata);

        final List<Mutation> mutations = new LinkedList<>();

        // SPARQL Query
        Mutation mutation = new Mutation(PCJ_METADATA_ROW_ID);
        final Value query = new Value( stringLexicoder.encode(metadata.getSparql()) );
        mutation.put(PCJ_METADATA_FAMILY, PCJ_METADATA_SPARQL_QUERY, query);
        mutations.add(mutation);

        // Cardinality
        mutation = new Mutation(PCJ_METADATA_ROW_ID);
        final Value cardinality = new Value( longLexicoder.encode(new Long(metadata.getCardinality())) );
        mutation.put(PCJ_METADATA_FAMILY, PCJ_METADATA_CARDINALITY, cardinality);
        mutations.add(mutation);

        //  Variable Orders
        final List<String> varOrderStrings = new ArrayList<>();
        for(final VariableOrder varOrder : metadata.getVarOrders()) {
            varOrderStrings.add( varOrder.toString() );
        }

        mutation = new Mutation(PCJ_METADATA_ROW_ID);
        final Value variableOrders = new Value( listLexicoder.encode(varOrderStrings) );
        mutation.put(PCJ_METADATA_FAMILY, PCJ_METADATA_VARIABLE_ORDERS, variableOrders);
        mutations.add(mutation);

        return mutations;
    }

    /**
     * Fetch the {@link PCJMetadata} from an Accumulo table.
     * <p>
     * This method assumes the PCJ table has already been created.
     *
     * @param accumuloConn - A connection to the Accumulo that hosts the PCJ table. (not null)
     * @param pcjTableName - The name of the table that will be search. (not null)
     * @return The PCJ Metadata that has been stolred in the in the PCJ Table.
     * @throws PCJStorageException The PCJ Table does not exist.
     */
    public PcjMetadata getPcjMetadata(
            final Connector accumuloConn,
            final String pcjTableName) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);

        Scanner scanner = null;
        try {
            // Create an Accumulo scanner that iterates through the metadata entries.
            scanner = accumuloConn.createScanner(pcjTableName, new Authorizations());
            final Iterator<Entry<Key, Value>> entries = scanner.iterator();

            // No metadata has been stored in the table yet.
            if(!entries.hasNext()) {
                throw new PCJStorageException("Could not find any PCJ metadata in the table named: " + pcjTableName);
            }

            // Fetch the metadata from the entries. Assuming they all have the same cardinality and sparql query.
            String sparql = null;
            Long cardinality = null;
            final Set<VariableOrder> varOrders = new HashSet<>();

            while(entries.hasNext()) {
                final Entry<Key, Value> entry = entries.next();
                final Text columnQualifier = entry.getKey().getColumnQualifier();
                final byte[] value = entry.getValue().get();

                if(columnQualifier.equals(PCJ_METADATA_SPARQL_QUERY)) {
                    sparql = stringLexicoder.decode(value);
                } else if(columnQualifier.equals(PCJ_METADATA_CARDINALITY)) {
                    cardinality = longLexicoder.decode(value);
                } else if(columnQualifier.equals(PCJ_METADATA_VARIABLE_ORDERS)) {
                    for(final String varOrderStr : listLexicoder.decode(value)) {
                        varOrders.add( new VariableOrder(varOrderStr) );
                    }
                }
            }

            return new PcjMetadata(sparql, cardinality, varOrders);

        } catch (final TableNotFoundException e) {
            throw new PCJStorageException("Could not add results to a PCJ because the PCJ table does not exist.", e);
        } finally {
            if(scanner != null) {
                scanner.close();
            }
        }
    }

    /**
     * Add a collection of results to a PCJ table. The table's cardinality will
     * be updated to include the new results.
     * <p>
     * This method assumes the PCJ table has already been created.
     *
     * @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 PCJStorageException The provided PCJ table doesn't exist, is missing the
     *   PCJ metadata, or the result could not be written to it.
     */
    public void addResults(
            final Connector accumuloConn,
            final String pcjTableName,
            final Collection<VisibilityBindingSet> results) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);
        checkNotNull(results);

        // Write a result to each of the variable orders that are in the table.
        writeResults(accumuloConn, pcjTableName, results);

        // Increment the cardinality of the query by the number of new results.
        if(accumuloConn.getInstance().getClass().equals(MockInstance.class)) {
        	updateMockCardinality(accumuloConn, pcjTableName, results.size());
        } else {
        	updateCardinality(accumuloConn, pcjTableName, results.size());
        }
    }

    /**
     * Get an {@link Iterator} over the {@link BindingSet}s that are stored in the PCJ table.
     *
     * @param accumuloConn - A connection to the Accumulo that hsots the PCJ table. (not null)
     * @param pcjTableName - The name of the PCJ table that will be scanned. (not null)
     * @param auths - the user's authorizations that will be used to scan the table. (not null)
     * @return An iterator over all of the {@link BindingSet}s that are stored as
     *   results for the PCJ.
     * @throws PCJStorageException The binding sets could not be fetched.
     */
    public CloseableIterator<BindingSet> listResults(final Connector accumuloConn, final String pcjTableName, final Authorizations auths) throws PCJStorageException {
        requireNonNull(pcjTableName);

        // Fetch the Variable Orders for the binding sets and choose one of them. It
        // doesn't matter which one we choose because they all result in the same output.
        final PcjMetadata metadata = getPcjMetadata(accumuloConn, pcjTableName);
        final VariableOrder varOrder = metadata.getVarOrders().iterator().next();

        try {
            // Fetch only the Binding Sets whose Variable Order matches the selected one.
            final Scanner scanner = accumuloConn.createScanner(pcjTableName, auths);
            scanner.fetchColumnFamily( new Text(varOrder.toString()) );

            // Return an Iterator that uses that scanner.
            return new ScannerBindingSetIterator(scanner, varOrder);

        } catch (final TableNotFoundException e) {
            throw new PCJStorageException(String.format("PCJ Table does not exist for name '%s'.", 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 PCJStorageException The provided PCJ table doesn't exist, is missing the
     *   PCJ metadata, or the result could not be written to it.
     */
    private void writeResults(
            final Connector accumuloConn,
            final String pcjTableName,
            final Collection<VisibilityBindingSet> results) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);
        checkNotNull(results);

        // Fetch the variable orders from the PCJ table.
        final PcjMetadata metadata = getPcjMetadata(accumuloConn, pcjTableName);

        // Write each result formatted using each of the variable orders.
        BatchWriter writer = null;
        try {
            writer = accumuloConn.createBatchWriter(pcjTableName, new BatchWriterConfig());
            for(final VisibilityBindingSet result : results) {
                final Set<Mutation> addResultMutations = makeWriteResultMutations(metadata.getVarOrders(), result);
                writer.addMutations( addResultMutations );
            }
        } catch (TableNotFoundException | MutationsRejectedException e) {
            throw new PCJStorageException("Could not add results to the PCJ table named: " + pcjTableName, e);
        } finally {
            if(writer != null) {
                try {
                    writer.close();
                } catch (final MutationsRejectedException e) {
                    throw new PCJStorageException("Could not add results to a PCJ table because some of the mutations were rejected.", e);
                }
            }
        }
    }

    /**
     * Create the {@link Mutations} required to write a new {@link BindingSet}
     * to a PCJ table for each {@link VariableOrder} that is provided.
     *
     * @param varOrders - The variables orders the result will be written to. (not null)
     * @param result - A new PCJ result. (not null)
     * @return Mutation that will write the result to a PCJ table.
     * @throws PCJStorageException The binding set could not be encoded.
     */
    private static Set<Mutation> makeWriteResultMutations(
            final Set<VariableOrder> varOrders,
            final VisibilityBindingSet result) throws PCJStorageException {
        checkNotNull(varOrders);
        checkNotNull(result);

        final Set<Mutation> mutations = new HashSet<>();
        final AccumuloPcjSerializer converter = new AccumuloPcjSerializer();
        VisibilityBindingSetSerDe bsSerDe = new VisibilityBindingSetSerDe();

        for(final VariableOrder varOrder : varOrders) {
            try {
                // Serialize the result to the variable order.
                final byte[] rowKey = converter.convert(result, varOrder);

                // Row ID = binding set values, Column Family = variable order of the binding set.
                final Mutation addResult = new Mutation(rowKey);
                final String visibility = result.getVisibility();
                addResult.put(varOrder.toString(), "", new ColumnVisibility(visibility), new Value(bsSerDe.serialize(result).toArray()));
                mutations.add(addResult);
            } catch(Exception e) {
                throw new PCJStorageException("Could not serialize a result.", e);
            }
        }

        return mutations;
    }

    /**
     * Update the cardinality of a PCJ by a {@code delta}.
     *
     * @param accumuloConn - A connection to the Accumulo that hosts the PCJ table. (not null)
     * @param pcjTableName - The name of the PCJ table that will have its cardinality updated. (not null)
     * @param delta - How much the cardinality will change.
     * @throws PCJStorageException The cardinality could not be updated.
     */
    private void updateCardinality(final Connector accumuloConn, final String pcjTableName, final long delta) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);

        ConditionalWriter conditionalWriter = null;
        try {
            conditionalWriter = accumuloConn.createConditionalWriter(pcjTableName, new ConditionalWriterConfig());

            boolean updated = false;
            while (!updated) {
                // Write the conditional update request to Accumulo.
                final long cardinality = getPcjMetadata(accumuloConn,pcjTableName).getCardinality();
                final ConditionalMutation mutation = makeUpdateCardinalityMutation(cardinality, delta);
                final ConditionalWriter.Result result = conditionalWriter.write(mutation);

                // Interpret the result.
                switch (result.getStatus()) {
                case ACCEPTED:
                    updated = true;
                    break;
                case REJECTED:
                    break;
                case UNKNOWN:
                    // We do not know if the mutation succeeded. At best, we
                    // can hope the metadata hasn't been updated
                    // since we originally fetched it and try again.
                    // Otherwise, continue forwards as if it worked. It's
                    // okay if this number is slightly off.
                    final long newCardinality = getPcjMetadata(accumuloConn,pcjTableName).getCardinality();
                    if (newCardinality != cardinality) {
                        updated = true;
                    }
                    break;
                case VIOLATED:
                    throw new PCJStorageException("The cardinality could not be updated because the commit violated a table constraint.");
                case INVISIBLE_VISIBILITY:
                    throw new PCJStorageException("The condition contains a visibility the updater can not satisfy.");
                }
            }
        } catch (AccumuloException | AccumuloSecurityException | TableNotFoundException e) {
            throw new PCJStorageException("Could not update the cardinality value of the PCJ Table named: " + pcjTableName, e);
        } finally {
            if (conditionalWriter != null) {
                conditionalWriter.close();
            }
        }
    }

    /**
     * Update the cardinality of a PCJ by a {@code delta}.
     *
     * This method updates the PCJ table cardinality using a BatchWriter in the event that
     * the Accumulo Connector is for a MockInstance.  In the event that the cardinality is
     * being updated asynchronously, there are no guarantees that the resulting cardinality
     * will be correct.
     *
     * @param accumuloConn - A connection to a Mock Accumulo Instance that hosts the PCJ table. (not null)
     * @param pcjTableName - The name of the PCJ table that will have its cardinality updated. (not null)
     * @param delta - How much the cardinality will change.
     * @throws PCJStorageException The cardinality could not be updated.
     */
    private void updateMockCardinality(final Connector accumuloConn, final String pcjTableName, final long delta) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);

        BatchWriter batchWriter = null;
        try {
            batchWriter = accumuloConn.createBatchWriter(pcjTableName, new BatchWriterConfig());
            final long cardinality = getPcjMetadata(accumuloConn, pcjTableName).getCardinality();
            final Mutation mutation = new Mutation(PCJ_METADATA_ROW_ID);
            final Value newCardinality = new Value(longLexicoder.encode(cardinality + delta));
            mutation.put(PCJ_METADATA_FAMILY, PCJ_METADATA_CARDINALITY, newCardinality);
            batchWriter.addMutation(mutation);
        } catch (TableNotFoundException | MutationsRejectedException e) {
            throw new PCJStorageException("Could not update the cardinality value of the PCJ Table named: " + pcjTableName, e);
        } finally {
            if (batchWriter != null) {
                try {
                    batchWriter.close();
                } catch (final MutationsRejectedException e) {
                    throw new PCJStorageException("Could not update the cardinality value of the PCJ Table named: " + pcjTableName, e);
                }
            }
        }
    }

    /**
     * Creates a {@link ConditionalMutation} that only updates the cardinality
     * of the PCJ table if the old value has not changed by the time this mutation
     * is committed to Accumulo.
     *
     * @param current - The current cardinality value.
     * @param delta - How much the cardinality will change.
     * @return The mutation that will perform the conditional update.
     */
    private static ConditionalMutation makeUpdateCardinalityMutation(final long current, final long delta) {
        // Try to update the cardinality by the delta.
        final ConditionalMutation mutation = new ConditionalMutation(PCJ_METADATA_ROW_ID);
        final Condition lastCardinalityStillCurrent = new Condition(
                PCJ_METADATA_FAMILY,
                PCJ_METADATA_CARDINALITY);

        // Require the old cardinality to be the value we just read.
        final byte[] currentCardinalityBytes = longLexicoder.encode( current );
        lastCardinalityStillCurrent.setValue( currentCardinalityBytes );
        mutation.addCondition(lastCardinalityStillCurrent);

        // If that is the case, then update to the new value.
        final Value newCardinality = new Value( longLexicoder.encode(current + delta) );
        mutation.put(PCJ_METADATA_FAMILY, PCJ_METADATA_CARDINALITY, newCardinality);
        return mutation;
    }

    /**
     * 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 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 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 table,
     *   the PCJ table does not exist, or the query that is being execute
     *   was malformed.
     */
    public void populatePcj(
            final Connector accumuloConn,
            final String pcjTableName,
            final RepositoryConnection ryaConn) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);
        checkNotNull(ryaConn);

        try {
            // Fetch the query that needs to be executed from the PCJ table.
            final PcjMetadata pcjMetadata = getPcjMetadata(accumuloConn, 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<VisibilityBindingSet> batch = new HashSet<>(1000);
            while(results.hasNext()) {
                batch.add( new VisibilityBindingSet(results.next()) );

                if(batch.size() == 1000) {
                    addResults(accumuloConn, pcjTableName, batch);
                    batch.clear();
                }
            }

            if(!batch.isEmpty()) {
                addResults(accumuloConn, pcjTableName, batch);
            }

        } catch (RepositoryException | MalformedQueryException | QueryEvaluationException e) {
            throw new PCJStorageException("Could not populate a PCJ table with Rya results for the table named: " + pcjTableName, e);
        }
    }

    private static final PcjVarOrderFactory DEFAULT_VAR_ORDER_FACTORY = new ShiftVarOrderFactory();

    /**
     * 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 accumuloConn - Connects to the accumulo that hosts the PCJ results. (not null)
     * @param pcjTableName - 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)
     * @param resultVariables - The variables that are included in the query's resulting binding sets. (not null)
     * @param pcjVarOrderFactory - An optional factory that indicates the various variable orders
     *   the results will be stored in. If one is not provided, then {@link ShiftVarOrderFactory}
     *   is used by default. (not null)
     * @throws PCJStorageException The PCJ table could not be create or the values from
     *   Rya were not able to be loaded into it.
     */
    public void createAndPopulatePcj(
            final RepositoryConnection ryaConn,
            final Connector accumuloConn,
            final String pcjTableName,
            final String sparql,
            final String[] resultVariables,
            final Optional<PcjVarOrderFactory> pcjVarOrderFactory) throws PCJStorageException {
        checkNotNull(ryaConn);
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);
        checkNotNull(sparql);
        checkNotNull(resultVariables);
        checkNotNull(pcjVarOrderFactory);

        // Create the PCJ's variable orders.
        final PcjVarOrderFactory varOrderFactory = pcjVarOrderFactory.or(DEFAULT_VAR_ORDER_FACTORY);
        final Set<VariableOrder> varOrders = varOrderFactory.makeVarOrders( new VariableOrder(resultVariables) );

        // Create the PCJ table in Accumulo.
        createPcjTable(accumuloConn, pcjTableName, varOrders, sparql);

        // Load historic matches from Rya into the PCJ table.
        populatePcj(accumuloConn, pcjTableName, ryaConn);
    }

    /**
     * List the table names of the PCJ index tables that are stored in Accumulo
     * for a specific instance of Rya.
     *
     * @param accumuloConn - Connects to the accumulo that hosts the PCJ indices. (not null)
     * @param ryaInstanceName - The name of the Rya instance. (not null)
     * @return A list of Accumulo table names that hold PCJ index data for a
     *   specific Rya instance.
     */
    public List<String> listPcjTables(final Connector accumuloConn, final String ryaInstanceName) {
        checkNotNull(accumuloConn);
        checkNotNull(ryaInstanceName);

        final List<String> pcjTables = new ArrayList<>();

        final String pcjPrefix = ryaInstanceName + "INDEX";
        boolean foundInstance = false;

        for(final String tableName : accumuloConn.tableOperations().list()) {
            if(tableName.startsWith(ryaInstanceName)) {
                // This table is part of the target Rya instance.
                foundInstance = true;

                if(tableName.startsWith(pcjPrefix)) {
                    pcjTables.add(tableName);
                }
            }

            else if(foundInstance) {
                // We have encountered the first table name that does not start
                // with the rya instance name after those that do. Because the
                // list is sorted, there can't be any more pcj tables for the
                // target instance in the list.
                break;
            }
        }

        return pcjTables;
    }

    /**
     * Deletes all of the rows that are in a PCJ index and sets its cardinality back to 0.
     *
     * @param accumuloConn - Connects to the Accumulo that hosts the PCJ indices. (not null)
     * @param pcjTableName - The name of the PCJ table that will be purged. (not null)
     * @throws PCJStorageException Either the rows could not be dropped from the
     *   PCJ table or the metadata could not be written back to the table.
     */
    public void purgePcjTable(final Connector accumuloConn, final String pcjTableName) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);

        // Fetch the metadaata from the PCJ table.
        final PcjMetadata oldMetadata = getPcjMetadata(accumuloConn, pcjTableName);

        // Delete all of the rows
        try {
            accumuloConn.tableOperations().deleteRows(pcjTableName, null, null);
        } catch (AccumuloException | AccumuloSecurityException | TableNotFoundException e) {
            throw new PCJStorageException("Could not delete the rows of data from PCJ table named: " + pcjTableName, e);
        }

        // Store the new metadata.
        final PcjMetadata newMetadata = new PcjMetadata(oldMetadata.getSparql(), 0L, oldMetadata.getVarOrders());
        final List<Mutation> mutations = makeWriteMetadataMutations(newMetadata);

        BatchWriter writer = null;
        try {
            writer = accumuloConn.createBatchWriter(pcjTableName, new BatchWriterConfig());
            writer.addMutations(mutations);
            writer.flush();
        } catch (final TableNotFoundException | MutationsRejectedException e) {
            throw new PCJStorageException("Could not rewrite the PCJ cardinality for table named '"
                    + pcjTableName + "'. This table will not work anymore.", e);
        } finally {
            if(writer != null) {
                try {
                    writer.close();
                } catch (final MutationsRejectedException e) {
                    throw new PCJStorageException("Could not close the batch writer.", e);
                }
            }
        }
    }

    /**
     * Drops a PCJ index from Accumulo.
     *
     * @param accumuloConn - Connects to the Accumulo that hosts the PCJ indices. (not null)
     * @param pcjTableName - The name of the PCJ table that will be dropped. (not null)
     * @throws PCJStorageException - The table could not be dropped because of
     *   a security exception or because it does not exist.
     */
    public void dropPcjTable(final Connector accumuloConn, final String pcjTableName) throws PCJStorageException {
        checkNotNull(accumuloConn);
        checkNotNull(pcjTableName);
        try {
            accumuloConn.tableOperations().delete(pcjTableName);
        } catch (AccumuloException | AccumuloSecurityException | TableNotFoundException e) {
            throw new PCJStorageException("Could not delete PCJ table named: " + pcjTableName, e);
        }
    }
}