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

import static org.apache.rya.api.resolver.RdfToRyaConversions.convertStatement;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.io.PrintStream;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
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.BatchWriterConfig;
import org.apache.accumulo.core.client.Connector;
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.admin.TableOperations;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.Text;
import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
import org.apache.rya.api.domain.RyaStatement;
import org.apache.rya.indexing.StatementConstraints;
import org.apache.rya.indexing.StatementSerializer;
import org.apache.rya.indexing.TemporalInstant;
import org.apache.rya.indexing.TemporalInstantRfc3339;
import org.apache.rya.indexing.TemporalInterval;
import org.apache.rya.indexing.accumulo.ConfigUtils;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.QueryEvaluationException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.google.common.collect.Lists;

/**
 * JUnit tests for TemporalIndexer and it's implementation AccumuloTemporalIndexer
 *
 * If you enjoy this test, please read RyaTemporalIndexerTest and YagoKBTest, which contain
 * many example SPARQL queries and updates and attempts to test independently of Accumulo:
 *
 *     extras/indexingSail/src/test/java/org.apache/rya/indexing/accumulo/RyaTemporalIndexerTest.java
 *     {@link org.apache.rya.indexing.accumulo.RyaTemporalIndexerTest}
 *     {@link org.apache.rya.indexing.accumulo.YagoKBTest.java}
 *
 * Remember, this class in instantiated fresh for each @test method.
 * so fields are reset, unless they are static.
 *
 * These are covered:
 *   Instance {before, equals, after} given Instance
 *   Instance {before, after, inside} given Interval
 *   Instance {hasBeginning, hasEnd} given Interval
 * And a few more.
 *
 *  The temporal predicates are from these ontologies: 
 *      http://linkedevents.org/ontology
 *      http://motools.sourceforge.net/event/event.html
 */
public final class AccumuloTemporalIndexerTest {
    // Configuration properties, this is reset per test in setup.
    Configuration conf;
    // temporal indexer to test, this is created for each test method by setup.
    AccumuloTemporalIndexer tIndexer;

    private static final String URI_PROPERTY_EVENT_TIME = "Property:event:time";
    private static final String URI_PROPERTY_CIRCA = "Property:circa";
    private static final String URI_PROPERTY_AT_TIME = "Property:atTime";
    private static final String STAT_COUNT = "count";
    private static final String STAT_KEYHASH = "keyhash";
    private static final String STAT_VALUEHASH = "valuehash";
    private static final StatementConstraints EMPTY_CONSTRAINTS = new StatementConstraints();

    // Assign this in setUpBeforeClass, store them in each test.
    // setup() deletes table before each test.
    static final Statement spo_B00_E01;
    static final Statement spo_B03_E20;
    static final Statement spo_B02_E29;
    static final Statement spo_B02_E30;
    static final Statement spo_B02_E40;
    static final Statement spo_B02_E31;
    static final Statement spo_B29_E30;
    static final Statement spo_B30_E32;

    // Instants:
    static final Statement spo_B02;
    static final int SERIES_OF_SECONDS = 41;
    static final Statement seriesSpo[] = new Statement[SERIES_OF_SECONDS];

    // These are shared for several tests. Only the seconds are different.
    // tvB03_E20 read as: interval Begins 3 seconds, ends at 20 seconds
    static final TemporalInterval tvB00_E01 = new TemporalInterval(//
            makeInstant(00), //
            makeInstant(01));
    static final TemporalInterval tvB29_E30= new TemporalInterval(//
            makeInstant(29), //
            makeInstant(30));
    static final TemporalInterval tvB30_E32= new TemporalInterval(//
            makeInstant(30), //
            makeInstant(32));
    static final TemporalInterval tvB03_E20 = new TemporalInterval(//
            makeInstant(03), //
            makeInstant(20));
    // 30 seconds, Begins earlier, ends later
    static final TemporalInterval tvB02_E30= new TemporalInterval(//
            makeInstant(02), //
            makeInstant(30));
    // use for interval after
    static final TemporalInterval tvB02_E29= new TemporalInterval(//
            makeInstant(02), //
            makeInstant(29));
    // same as above, but ends in the middle
    static final TemporalInterval tvB02_E31 = new TemporalInterval(//
            makeInstant(02), //
            makeInstant(31));
    // same as above, but ends even later
    static final TemporalInterval tvB02_E40 = new TemporalInterval(//
            makeInstant(02), //
            makeInstant(40));
    // instant, match beginnings of several above, before tiB03_E20
    static final TemporalInstant tsB02 = makeInstant(02);
    // instant, after all above
    static final TemporalInstant tsB04 = makeInstant(04);

    // Create a series of instants about times 0 - 40 seconds
    static final TemporalInstant seriesTs[];
    static {
        seriesTs = new TemporalInstant[SERIES_OF_SECONDS];
        for (int i = 0; i <= 40; i++)
            seriesTs[i] = makeInstant(i);
    }

    /**
     * Make an uniform instant with given seconds.
     */
    static TemporalInstant makeInstant(int secondsMakeMeUnique) {
        return new TemporalInstantRfc3339(2015, 12, 30, 12, 00, secondsMakeMeUnique);
    }

    static {
        // Setup the statements only once. Each test will store some of these in there own index table.
        ValueFactory vf = SimpleValueFactory.getInstance();
        IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);
        // tiB03_E20 read as: time interval that Begins 3 seconds, ends at 20 seconds,
        // Each time element the same, except seconds. year, month, .... minute are the same for each statement below.
        spo_B00_E01 = vf.createStatement(vf.createIRI("foo:event0"), pred1_atTime, vf.createLiteral(tvB00_E01.toString()));
        spo_B02_E29 = vf.createStatement(vf.createIRI("foo:event2"), pred1_atTime, vf.createLiteral(tvB02_E29.toString()));
        spo_B02_E30 = vf.createStatement(vf.createIRI("foo:event2"), pred1_atTime, vf.createLiteral(tvB02_E30.toString()));
        spo_B02_E31 = vf.createStatement(vf.createIRI("foo:event3"), pred1_atTime, vf.createLiteral(tvB02_E31.toString()));
        spo_B02_E40 = vf.createStatement(vf.createIRI("foo:event4"), pred1_atTime, vf.createLiteral(tvB02_E40.toString()));
        spo_B03_E20 = vf.createStatement(vf.createIRI("foo:event5"), pred1_atTime, vf.createLiteral(tvB03_E20.toString()));
        spo_B29_E30 = vf.createStatement(vf.createIRI("foo:event1"), pred1_atTime, vf.createLiteral(tvB29_E30.toString()));
        spo_B30_E32 = vf.createStatement(vf.createIRI("foo:event1"), pred1_atTime, vf.createLiteral(tvB30_E32.toString()));
        spo_B02 = vf.createStatement(vf.createIRI("foo:event6"), pred1_atTime, vf.createLiteral(tsB02.getAsReadable()));

        // Create statements about time instants 0 - 40 seconds
        for (int i = 0; i < seriesTs.length; i++) {
            seriesSpo[i] = vf.createStatement(vf.createIRI("foo:event0" + i), pred1_atTime, vf.createLiteral(seriesTs[i].getAsReadable()));
        }

    }

    /**
     * @throws java.lang.Exception
     */
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }

    /**
     * @throws java.lang.Exception
     */
    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    /**
     * @throws java.lang.Exception
     */
    @Before
    public void setUp() throws Exception {
        conf = new Configuration();
        conf.set(RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX, "triplestore_");
        conf.setBoolean(ConfigUtils.USE_MOCK_INSTANCE, true);
        // The temporal predicates are from http://linkedevents.org/ontology
        // and http://motools.sourceforge.net/event/event.html
        conf.setStrings(ConfigUtils.TEMPORAL_PREDICATES_LIST, ""
                + URI_PROPERTY_AT_TIME + ","
                + URI_PROPERTY_CIRCA + ","
                + URI_PROPERTY_EVENT_TIME);

        tIndexer = new AccumuloTemporalIndexer();
        tIndexer.setConf(conf);
        Connector connector = ConfigUtils.getConnector(conf);
        MultiTableBatchWriter mt_bw = connector.createMultiTableBatchWriter(new BatchWriterConfig());
        tIndexer.setConnector(connector);
        tIndexer.setMultiTableBatchWriter(mt_bw);
        tIndexer.init();
    }

    /**
     * @throws java.lang.Exception
     */
    @After
    public void tearDown() throws Exception {
    	String indexTableName = tIndexer.getTableName();
        tIndexer.close();
        TableOperations tableOps = ConfigUtils.getConnector(conf).tableOperations();

        if (tableOps.exists(indexTableName))
            tableOps.delete(indexTableName);
    }

    /**
     * Test method for {@link AccumuloTemporalIndexer#TemporalIndexerImpl(org.apache.hadoop.conf.Configuration)} .
     *
     * @throws TableExistsException
     * @throws TableNotFoundException
     * @throws AccumuloSecurityException
     * @throws AccumuloException
     * @throws IOException
     */
    @Test
    public void testTemporalIndexerImpl()
            throws AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, IOException {
        assertNotNull("Constructed.", tIndexer.toString());
    }

    /**
     * Test method for {@link AccumuloTemporalIndexer#storeStatement(convertStatement(org.eclipse.rdf4j.model.Statement)}
     *
     * @throws NoSuchAlgorithmException
     */
    @Test
    public void testStoreStatement() throws IOException, AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, NoSuchAlgorithmException {
        // count rows expected to store:
        int rowsStoredExpected = 0;

        ValueFactory vf = SimpleValueFactory.getInstance();

        IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);
        IRI pred2_circa = vf.createIRI(URI_PROPERTY_CIRCA);

        // Should not be stored because they are not in the predicate list
        String validDateStringWithThirteens = "1313-12-13T13:13:13Z";
        tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj1"), RDFS.LABEL, vf.createLiteral(validDateStringWithThirteens))));

        // Test: Should not store an improper date, and log a warning (log warning not tested).
        final String invalidDateString = "ThisIsAnInvalidDate";
//        // Silently logs a warning for bad dates.  Old: Set true when we catch the error:
//        boolean catchErrorThrownCorrectly = false;
//        try {
            tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj2"), pred1_atTime, vf.createLiteral(invalidDateString))));
//        } catch (IllegalArgumentException e) {
//            catchErrorThrownCorrectly = true;
//            Assert.assertTrue(
//                    "Invalid date parse error should include the invalid string. message=" + e.getMessage(),
//                    e.getMessage().contains(invalidDateString));
//        }
//        Assert.assertTrue("Invalid date parse error should be thrown for this bad date=" + invalidDateString, catchErrorThrownCorrectly);

        // These are different datetimes instant but from different time zones.
        // This is an arbitrary zone, BRST=Brazil, better if not local.
        // same as "2015-01-01T01:59:59Z"
        final String testDate2014InBRST = "2014-12-31T23:59:59-02:00";
        // next year, same as "2017-01-01T01:59:59Z"
        final String testDate2016InET = "2016-12-31T20:59:59-05:00";

        // These should be stored because they are in the predicate list.
        // BUT they will get converted to the same exact datetime in UTC.
        Statement s3 = vf.createStatement(vf.createIRI("foo:subj3"), pred1_atTime, vf.createLiteral(testDate2014InBRST));
        Statement s4 = vf.createStatement(vf.createIRI("foo:subj4"), pred2_circa, vf.createLiteral(testDate2016InET));
        tIndexer.storeStatement(convertStatement(s3));
        rowsStoredExpected++;
        tIndexer.storeStatement(convertStatement(s4));
        rowsStoredExpected++;

        // This should not be stored because the object is not a literal
        tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj5"), pred1_atTime, vf.createIRI("in:valid"))));

        tIndexer.flush();

        int rowsStoredActual = printTables("junit testing: Temporal entities stored in testStoreStatement", null, null);
        assertEquals("Number of rows stored.", rowsStoredExpected*4, rowsStoredActual); // 4 index entries per statement

    }

    @Test
    public void testDelete() throws IOException, AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, NoSuchAlgorithmException {
        // count rows expected to store:
        int rowsStoredExpected = 0;

        ValueFactory vf = SimpleValueFactory.getInstance();

        IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);
        IRI pred2_circa = vf.createIRI(URI_PROPERTY_CIRCA);

        final String testDate2014InBRST = "2014-12-31T23:59:59-02:00";
        final String testDate2016InET = "2016-12-31T20:59:59-05:00";

        // These should be stored because they are in the predicate list.
        // BUT they will get converted to the same exact datetime in UTC.
        Statement s1 = vf.createStatement(vf.createIRI("foo:subj3"), pred1_atTime, vf.createLiteral(testDate2014InBRST));
        Statement s2 = vf.createStatement(vf.createIRI("foo:subj4"), pred2_circa, vf.createLiteral(testDate2016InET));
        tIndexer.storeStatement(convertStatement(s1));
        rowsStoredExpected++;
        tIndexer.storeStatement(convertStatement(s2));
        rowsStoredExpected++;

        tIndexer.flush();

        int rowsStoredActual = printTables("junit testing: Temporal entities stored in testDelete before delete", System.out, null);
        Assert.assertEquals("Number of rows stored.", rowsStoredExpected*4, rowsStoredActual); // 4 index entries per statement

        tIndexer.deleteStatement(convertStatement(s1));
        tIndexer.deleteStatement(convertStatement(s2));

        int afterDeleteRowsStoredActual = printTables("junit testing: Temporal entities stored in testDelete after delete", System.out, null);
        Assert.assertEquals("Number of rows stored after delete.", 0, afterDeleteRowsStoredActual);
    }

    @Test
    public void testStoreStatementWithInterestingLiterals() throws Exception {
        ValueFactory vf = SimpleValueFactory.getInstance();

        IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);

        tIndexer.storeStatement(convertStatement(vf.createStatement(
                vf.createIRI("foo:subj2"),
                pred1_atTime,
                vf.createLiteral("A number of organizations located, gathered, or classed together. [Derived from Concise Oxford English Dictionary, 11th Edition, 2008]"))));

        int rowsStoredActual = printTables("junit testing: Temporal entities stored in testStoreStatement", null, null);
        Assert.assertEquals("Number of rows stored.", 0, rowsStoredActual); // 4 index entries per statement
    }

    /**
     * Test method for {@link AccumuloTemporalIndexer#storeStatement(convertStatement(org.eclipse.rdf4j.model.Statement)}
     *
     * @throws NoSuchAlgorithmException
     */
    @Test
    public void testStoreStatementBadInterval() throws IOException, AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, NoSuchAlgorithmException {
        // count rows expected to store:
        int rowsStoredExpected = 0;

        ValueFactory vf = SimpleValueFactory.getInstance();
        IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);

        // Test: Should not store an improper date interval, and log a warning (log warning not tested).
        final String invalidDateIntervalString="[bad,interval]";
        // Silently logs a warning for bad dates.
        tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj1"), pred1_atTime, vf.createLiteral(invalidDateIntervalString))));

        final String validDateIntervalString="[2016-12-31T20:59:59-05:00,2016-12-31T21:00:00-05:00]";
        tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj2"), pred1_atTime, vf.createLiteral(validDateIntervalString))));
        rowsStoredExpected++;

        tIndexer.flush();

        int rowsStoredActual = printTables("junit testing: Temporal intervals stored in testStoreStatement", null, null);
        Assert.assertEquals("Only good intervals should be stored.", rowsStoredExpected*2, rowsStoredActual); // 2 index entries per interval statement
    }

    @Test
    public void testStoreStatementsSameTime() throws IOException, NoSuchAlgorithmException, AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException {
        ValueFactory vf = SimpleValueFactory.getInstance();
        IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);
        IRI pred2_circa = vf.createIRI(URI_PROPERTY_CIRCA);

        // These are the same datetime instant but from different time
        // zones.
        // This is an arbitrary zone, BRST=Brazil, better if not local.
        final String ZONETestDateInBRST = "2014-12-31T23:59:59-02:00";
        final String ZONETestDateInZulu = "2015-01-01T01:59:59Z";
        final String ZONETestDateInET = "2014-12-31T20:59:59-05:00";

        // These all should be stored because they are in the predicate list.
        // BUT they will get converted to the same exact datetime in UTC.
        // So we have to make the key distinct! Good luck indexer!
        Statement s1 = vf.createStatement(vf.createIRI("foo:subj1"), pred2_circa, vf.createLiteral(ZONETestDateInET));
        Statement s2 = vf.createStatement(vf.createIRI("foo:subj2"), pred1_atTime, vf.createLiteral(ZONETestDateInZulu));
        Statement s3 = vf.createStatement(vf.createIRI("foo:subj3"), pred1_atTime, vf.createLiteral(ZONETestDateInBRST));
        int rowsStoredExpected = 0;
        tIndexer.storeStatement(convertStatement(s1));
        rowsStoredExpected++;
        tIndexer.storeStatement(convertStatement(s2));
        rowsStoredExpected++;
        tIndexer.storeStatement(convertStatement(s3));
        rowsStoredExpected++;
        int rowsStoredActual = printTables("junit testing: Duplicate times stored", null /*System.out*/, null);
        Assert.assertEquals("Number of Duplicate times stored, 1 means duplicates not handled correctly.", rowsStoredExpected*4, rowsStoredActual);
    }

    /**
     * Test method for {@link AccumuloTemporalIndexer#storeStatements(java.util.Collection)} .
     *
     * @throws TableExistsException
     * @throws TableNotFoundException
     * @throws AccumuloSecurityException
     * @throws AccumuloException
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws NoSuchAlgorithmException
     */
    @Test
    public void testStoreStatements()
            throws AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, IllegalArgumentException, IOException,
            NoSuchAlgorithmException {
        long valueHash = 0;
        Collection<Statement> statements = new ArrayList<Statement>(70);
        statements.addAll(Arrays.asList(seriesSpo));
        int rowsStoredExpected = statements.size()*4;  // instants store 4 each
        // hash the expected output:
        for (Statement statement : statements) {
            valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(statement)));
            valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(statement)));
            valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(statement)));
            valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(statement)));
        }
        statements.add(spo_B02_E30);
        rowsStoredExpected += 2; // intervals store two dates
        statements.add(spo_B30_E32);
        rowsStoredExpected += 2; // intervals store two dates
        valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(spo_B02_E30)));
        valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(spo_B02_E30)));
        valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(spo_B30_E32)));
        valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(spo_B30_E32)));
        // duplicates will overwrite old ones, no change in the output except timestamps
        statements.add(spo_B30_E32);
        statements.add(spo_B30_E32);

        List<RyaStatement> ryaStatements = Lists.newArrayList();
        for (Statement s : statements){ ryaStatements.add(convertStatement(s));}
        tIndexer.storeStatements(ryaStatements);

        Map<String, Long> statistics = new HashMap<String, Long>();
        int rowsStoredActual = printTables("junit testing: StoreStatements multiple statements", null, statistics);
        Assert.assertEquals("Number of rows stored.", rowsStoredExpected, rowsStoredActual); // 4 index entries per statement
        Assert.assertEquals("value hash.", valueHash, statistics.get(STAT_VALUEHASH).longValue());
    }

    /**
     * test this classe's hash method to check un-ordered results.
     */
    @Test
    public void testSelfTestHashMethod() {
        // self test on the hash method:
        long hash01dup1 = hasher(0, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
        long hash01dup2 = hasher(0, new byte[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 });
        Assert.assertEquals("same numbers, different sequence, hash should be the same.", hash01dup1, hash01dup2);

        // this one fails for sum hash, passes for XOR
        long hash02dup1 = hasher(0, new byte[] { 123, 2, 1, 1 });
        hash02dup1 = hasher(hash02dup1, new byte[] { 123, 1, 1, 2 });
        long hash02dup2 = hasher(0, new byte[] { 123, 1, 1, 2 });
        hash02dup2 = hasher(hash02dup2, new byte[] { 123, 1, 3, 0, 0 });
        Assert.assertTrue("Different numbers, should be different hashes: " + hash02dup1 + " != " + hash02dup2, hash02dup1 != hash02dup2);
    }
    /**
     * Test instant equal to a given instant.
     * From the series: instant {equal, before, after} instant
     * @throws AccumuloSecurityException
     * @throws AccumuloException
     * @throws TableNotFoundException
     */
    @Test
    public void testQueryInstantEqualsInstant() throws IOException, QueryEvaluationException, TableNotFoundException, AccumuloException, AccumuloSecurityException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));
        int expectedStoreCount = 5 * 2; // two entries for intervals

        // seriesSpo[s] and seriesTs[s] are statements and instant for s seconds after the uniform time.
        int searchForSeconds = 5;
        int expectedResultCount = 1;
        for (int s = 0; s <= searchForSeconds + 3; s++) { // <== logic here
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            expectedStoreCount+=4; //4 entries per statement.
        }
        tIndexer.flush();

        int rowsStoredActual = printTables("junit testing: testQueryInstantEqualsInstant 0 to 8 seconds and 5 intervals stored. expectedStoreCount="+expectedStoreCount, null /*System.out*/, null);
        Assert.assertEquals("Should find count of rows.", expectedStoreCount, rowsStoredActual);

        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryInstantEqualsInstant(seriesTs[searchForSeconds], EMPTY_CONSTRAINTS); // <== logic here
        int count = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            Statement nextExpectedStatement = seriesSpo[searchForSeconds]; // <== logic here
            assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
            count++;
        }
        Assert.assertEquals("Should find count of rows.", expectedResultCount, count);

    }

    /**
     * Test instant after a given instant.
     * From the series: instant {equal, before, after} instant
     * @throws AccumuloSecurityException
     * @throws AccumuloException
     * @throws TableNotFoundException
     */
    @Test
    public void testQueryInstantAfterInstant() throws IOException, QueryEvaluationException, TableNotFoundException, AccumuloException, AccumuloSecurityException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));

        // seriesSpo[s] and seriesTs[s] are statements and instant for s seconds after the uniform time.
        int searchForSeconds = 4;
        int expectedResultCount = 9;
        for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
        }
        tIndexer.flush();
        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryInstantAfterInstant(seriesTs[searchForSeconds], EMPTY_CONSTRAINTS);
        int count = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            Statement nextExpectedStatement = seriesSpo[searchForSeconds + count + 1]; // <== logic here
            assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
            count++;
        }
        Assert.assertEquals("Should find count of rows.", expectedResultCount, count);
    }
    /**
     * Test instant before a given instant.
     * From the series: instant {equal, before, after} instant
     */
    @Test
    public void testQueryInstantBeforeInstant() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));

        // seriesSpo[s] and seriesTs[s] are statements and instant for s seconds after the uniform time.
        int searchForSeconds = 4;
        int expectedResultCount = 4;
        for (int s = 0; s <= searchForSeconds + 15; s++) { // <== logic here
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
        }
        tIndexer.flush();
        CloseableIteration<Statement, QueryEvaluationException> iter;

        iter = tIndexer.queryInstantBeforeInstant(seriesTs[searchForSeconds], EMPTY_CONSTRAINTS);
        int count = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            Statement nextExpectedStatement = seriesSpo[count]; // <== logic here
            assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
            count++;
        }
        Assert.assertEquals("Should find count of rows.", expectedResultCount, count);
    }

    /**
     * Test instant before given interval.
     * From the series:  Instance {before, after, inside} given Interval
     */
    @Test
    public void testQueryInstantBeforeInterval() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));

        // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time.
        TemporalInterval searchForSeconds = tvB02_E31;
        int expectedResultCount = 2; // 00 and 01 seconds.
        for (int s = 0; s <= 40; s++) { // <== logic here
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
        }
        tIndexer.flush();
        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryInstantBeforeInterval(searchForSeconds, EMPTY_CONSTRAINTS);
        int count = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            Statement nextExpectedStatement = seriesSpo[count]; // <== logic here
            assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
            count++;
        }
        Assert.assertEquals("Should find count of rows.", expectedResultCount, count);
    }

    /**
     * Test instant after given interval.
     * Instance {before, after, inside} given Interval
     */
    @Test
    public void testQueryInstantAfterInterval() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));

        // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time.
        TemporalInterval searchAfterInterval = tvB02_E31; // from 2 to 31 seconds
        int endingSeconds = 31;
        int expectedResultCount = 9; // 32,33,...,40 seconds.
        for (int s = 0; s <= endingSeconds + expectedResultCount; s++) { // <== logic here
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
        }
        tIndexer.flush();
        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryInstantAfterInterval(searchAfterInterval, EMPTY_CONSTRAINTS);
        int count = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            Statement nextExpectedStatement = seriesSpo[count + endingSeconds + 1]; // <== logic here
            assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
            count++;
        }
        Assert.assertEquals("Should find count of rows.", expectedResultCount, count);
    }

    /**
     * Test instant inside given interval.
     * Instance {before, after, inside} given Interval
     */
    @Test
    public void testQueryInstantInsideInterval() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));

        // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time.
        TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds
        int beginningSeconds = 2; // <== logic here, and next few lines.
        int endingSeconds = 31;
        int expectedResultCount = endingSeconds - beginningSeconds - 1; // 3,4,...,30 seconds.
        for (int s = 0; s <= 40; s++) {
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
        }
        tIndexer.flush();
        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryInstantInsideInterval(searchInsideInterval, EMPTY_CONSTRAINTS);
        int count = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            Statement nextExpectedStatement = seriesSpo[count + beginningSeconds + 1]; // <== logic here
            assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
            count++;
        }
        Assert.assertEquals("Should find count of rows.", expectedResultCount, count);
    }
    /**
     * Test instant is the Beginning of the given interval.
     * from the series: Instance {hasBeginning, hasEnd} Interval
     */
    @Test
    public void testQueryInstantHasBeginningInterval() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));

        // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time.
        TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds
        int searchSeconds = 2; // <== logic here, and next few lines.
        int expectedResultCount = 1; // 2 seconds.
        for (int s = 0; s <= 10; s++) {
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
        }
        tIndexer.flush();
        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryInstantHasBeginningInterval(searchInsideInterval, EMPTY_CONSTRAINTS);
        int count = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            Statement nextExpectedStatement = seriesSpo[searchSeconds]; // <== logic here
            assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
            count++;
        }
        Assert.assertEquals("Should find count of rows.", expectedResultCount, count);
    }
    /**
     * Test instant is the end of the given interval.
     * from the series: Instance {hasBeginning, hasEnd} Interval
     */
    @Test
    public void testQueryInstantHasEndInterval()  throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));

        // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time.
        TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds
        int searchSeconds = 31; // <== logic here, and next few lines.
        int expectedResultCount = 1; // 31 seconds.
        for (int s = 0; s <= 40; s++) {
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
        }
        tIndexer.flush();
        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryInstantHasEndInterval(searchInsideInterval, EMPTY_CONSTRAINTS);
        int count = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            Statement nextExpectedStatement = seriesSpo[searchSeconds]; // <== logic here
            assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
            count++;
        }
        Assert.assertEquals("Should find count of rows.", expectedResultCount, count);
    }

    /**
     * Test method for
     * {@link org.apache.rya.indexing.accumulo.temporal.AccumuloTemporalIndexer#queryIntervalEquals(TemporalInterval, StatementConstraints)}
     * .
     * @throws IOException
     * @throws QueryEvaluationException
     *
     */
    @Test
    public void testQueryIntervalEquals() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));
        tIndexer.storeStatement(convertStatement(seriesSpo[4])); // instance at 4 seconds
        tIndexer.flush();

        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryIntervalEquals(tvB02_E40, EMPTY_CONSTRAINTS);
        // Should be found twice:
        Assert.assertTrue("queryIntervalEquals: spo_B02_E40 should be found, but actually returned empty results. spo_B02_E40=" + spo_B02_E40, iter.hasNext());
        Assert.assertTrue("queryIntervalEquals: spo_B02_E40 should be found, but does not match.", spo_B02_E40.equals(iter.next()));
        Assert.assertFalse("queryIntervalEquals: Find no more than one, but actually has more.", iter.hasNext());
    }

    /**
     * Test interval before a given interval, for method:
     * {@link AccumuloTemporalIndexer#queryIntervalBefore(TemporalInterval, StatementConstraints)}.
     *
     * @throws IOException
     * @throws QueryEvaluationException
     */
    @Test
    public void testQueryIntervalBefore() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        tIndexer.storeStatement(convertStatement(spo_B00_E01));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        // instants should be ignored.
        tIndexer.storeStatement(convertStatement(spo_B30_E32));
        tIndexer.storeStatement(convertStatement(seriesSpo[1])); // instance at 1 seconds
        tIndexer.storeStatement(convertStatement(seriesSpo[2]));
        tIndexer.storeStatement(convertStatement(seriesSpo[31]));
        tIndexer.flush();

        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryIntervalBefore(tvB02_E31, EMPTY_CONSTRAINTS);
        // Should be found twice:
        Assert.assertTrue("spo_B00_E01 should be found, but actually returned empty results. spo_B00_E01=" + spo_B00_E01, iter.hasNext());
        Assert.assertTrue("spo_B00_E01 should be found, but found another.", spo_B00_E01.equals(iter.next()));
        Assert.assertFalse("Find no more than one, but actually has more.", iter.hasNext());
    }

    /**
     * interval is after the given interval.  Find interval beginnings after the endings of the given interval.
     * {@link AccumuloTemporalIndexer#queryIntervalAfter(TemporalInterval, StatementContraints).
     *
     * @throws IOException
     * @throws QueryEvaluationException
     */
    @Test
    public void testQueryIntervalAfter() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        tIndexer.storeStatement(convertStatement(spo_B00_E01));
        tIndexer.storeStatement(convertStatement(spo_B02_E29)); //<- after this one.
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B29_E30));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));
        // instants should be ignored.
        tIndexer.storeStatement(convertStatement(spo_B02));
        tIndexer.storeStatement(convertStatement(seriesSpo[1])); // instance at 1 seconds
        tIndexer.storeStatement(convertStatement(seriesSpo[2]));
        tIndexer.storeStatement(convertStatement(seriesSpo[31]));
        tIndexer.flush();

        CloseableIteration<Statement, QueryEvaluationException> iter;
        iter = tIndexer.queryIntervalAfter(tvB02_E29, EMPTY_CONSTRAINTS);
        // Should be found twice:
        Assert.assertTrue("spo_B30_E32 should be found, but actually returned empty results. spo_B30_E32=" + spo_B30_E32, iter.hasNext());
        Statement s = iter.next();
        Assert.assertTrue("spo_B30_E32 should be found, but found another. spo_B30_E32="+spo_B30_E32+", but found="+s, spo_B30_E32.equals(s));
        Assert.assertFalse("Find no more than one, but actually has more.", iter.hasNext());

    }

    /**
     * Test instant after a given instant WITH two different predicates as constraints.
     */
    @Test
    public void testQueryWithMultiplePredicates() throws IOException, QueryEvaluationException {
        // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds
        // these should not match as they are not instances.
        tIndexer.storeStatement(convertStatement(spo_B03_E20));
        tIndexer.storeStatement(convertStatement(spo_B02_E30));
        tIndexer.storeStatement(convertStatement(spo_B02_E40));
        tIndexer.storeStatement(convertStatement(spo_B02_E31));
        tIndexer.storeStatement(convertStatement(spo_B30_E32));

        // seriesSpo[s] and seriesTs[s] are statements and instant for s seconds after the uniform time.
        int searchForSeconds = 4;
        int expectedResultCount = 9;
        for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here
            tIndexer.storeStatement(convertStatement(seriesSpo[s]));
        }
        ValueFactory vf = SimpleValueFactory.getInstance();
        IRI pred3_CIRCA_ = vf.createIRI(URI_PROPERTY_CIRCA);  // this one to ignore.
        IRI pred2_eventTime = vf.createIRI(URI_PROPERTY_EVENT_TIME);
        IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);

        // add the predicate = EventTime ; Store in an array for verification.
        Statement[] SeriesTs_EventTime = new Statement[expectedResultCount+1];
        for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here
            Statement statement = vf.createStatement(vf.createIRI("foo:EventTimeSubj0" + s), pred2_eventTime, vf.createLiteral(seriesTs[s].getAsReadable()));
            tIndexer.storeStatement(convertStatement(statement));
            if (s>searchForSeconds)
                SeriesTs_EventTime[s - searchForSeconds -1 ] = statement;
        }
        // add the predicate = CIRCA ; to be ignored because it is not in the constraints.
        for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here
            Statement statement = vf.createStatement(vf.createIRI("foo:CircaEventSubj0" + s), pred3_CIRCA_, vf.createLiteral(seriesTs[s].getAsReadable()));
            tIndexer.storeStatement(convertStatement(statement));
        }
        tIndexer.flush();
        CloseableIteration<Statement, QueryEvaluationException> iter;
        StatementConstraints constraints = new StatementConstraints();
        constraints.setPredicates(new HashSet<IRI>(Arrays.asList( pred2_eventTime,  pred1_atTime )));

        iter = tIndexer.queryInstantAfterInstant(seriesTs[searchForSeconds], constraints); // EMPTY_CONSTRAINTS);//
        int count_AtTime = 0;
        int count_EventTime = 0;
        while (iter.hasNext()) {
            Statement s = iter.next();
            //System.out.println("testQueryWithMultiplePredicates result="+s);
            Statement nextExpectedStatement = seriesSpo[searchForSeconds + count_AtTime + 1]; // <== logic here
            if (s.getPredicate().equals(pred1_atTime)) {
                assertTrue("Should match atTime: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
                count_AtTime++;
            }
            else if (s.getPredicate().equals(pred2_eventTime)) {
                assertTrue("Should match eventTime: " + SeriesTs_EventTime[count_EventTime] + " == " + s, SeriesTs_EventTime[count_EventTime].equals(s));
                count_EventTime++;
            } else {
                assertTrue("This predicate should not be returned: "+s, false);
            }

        }

        Assert.assertEquals("Should find count of atTime    rows.", expectedResultCount, count_AtTime);
        Assert.assertEquals("Should find count of eventTime rows.", expectedResultCount, count_EventTime);
    }


    /**
     * Test method for {@link AccumuloTemporalIndexer#getIndexablePredicates()} .
     *
     * @throws TableExistsException
     * @throws TableNotFoundException
     * @throws AccumuloSecurityException
     * @throws AccumuloException
     * @throws IOException
     */
    @Test
    public void testGetIndexablePredicates() throws AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, IOException {
        Set<IRI> p = tIndexer.getIndexablePredicates();
        Assert.assertEquals("number of predicates returned:", 3, p.size());
    }

    /**
     * Count all the entries in the temporal index table, return the count.
     * Uses printTables for reliability.
     *
     */
    public int countAllRowsInTable() throws AccumuloException, AccumuloSecurityException, TableNotFoundException, NoSuchAlgorithmException {
        return printTables("Counting rows.", null, null);
    }

    /**
     * Print and gather statistics on the entire index table.
     *
     * @param description
     *            Printed to the console to find the test case.
     * @param out
     *            null or System.out or other output to send a listing.
     * @param statistics
     *            Hashes, sums, and counts for assertions.
     * @return Count of entries in the index table.
     */
    public int printTables(String description, PrintStream out, Map<String, Long> statistics)
            throws TableNotFoundException, AccumuloException, AccumuloSecurityException
    {
        if (out == null) {
            out = new PrintStream(new NullOutputStream());
        }
        out.println("-- start printTables() -- " + description);
        String FORMAT = "%-20s  %-20s  %-40s  %-40s\n";
        int rowsPrinted = 0;
        long keyHasher = 0;
        long valueHasher = 0;
        final String indexTableName = tIndexer.getTableName();
        out.println("Reading : " + indexTableName);
        out.format(FORMAT, "--Row--", "--ColumnFamily--", "--ColumnQualifier--", "--Value--");

        Scanner s = ConfigUtils.getConnector(conf).createScanner(indexTableName, Authorizations.EMPTY);
        for (Entry<Key, org.apache.accumulo.core.data.Value> entry : s) {
            rowsPrinted++;
            Key k = entry.getKey();
            out.format(FORMAT, toHumanString(k.getRow()),
                    toHumanString(k.getColumnFamily()),
                    toHumanString(k.getColumnQualifier()),
                    toHumanString(entry.getValue()));
            keyHasher = hasher(keyHasher, (StringUtils.getBytesUtf8(entry.getKey().toStringNoTime())));
            valueHasher = hasher(valueHasher, (entry.getValue().get()));
        }
        out.println();

        if (statistics != null) {
            statistics.put(STAT_COUNT, (long) rowsPrinted);
            statistics.put(STAT_KEYHASH, keyHasher);
            statistics.put(STAT_VALUEHASH, valueHasher);
        }

        return rowsPrinted;

    }

    /**
     * Order independent hashcode.
     * Read more: http://stackoverflow.com/questions/18021643/hashing-a-set-of-integers-in-an-order-independent-way
     *
     * @param hashcode
     * @param list
     * @return
     */
    private static long hasher(long hashcode, byte[] list) {
        long sum = 0;
        for (byte val : list) {
            sum += 1L + val;
        }
        hashcode ^= sum;
        return hashcode;
    }

    /**
     * convert a non-utf8 byte[] and text and value to string and show unprintable bytes as {xx} where x is hex.
     * @param value
     * @return Human readable representation.
     */
    static String toHumanString(Value value) {
        return toHumanString(value==null?null:value.get());
    }
    static String toHumanString(Text text) {
        return toHumanString(text==null?null:text.copyBytes());
    }
    static String toHumanString(byte[] bytes) {
        if (bytes==null)
            return "{null}";
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            if ((b > 0x7e) || (b < 32)) {
                sb.append("{");
                sb.append(Integer.toHexString( b & 0xff )); // Lop off the sign extended ones.
                sb.append("}");
            } else if (b == '{'||b == '}') { // Escape the literal braces.
                sb.append("{");
                sb.append((char)b);
                sb.append("}");
            } else
                sb.append((char)b);
        }
        return sb.toString();
    }
}
