package org.apache.rya.indexing.mongo;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


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

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashSet;

import org.apache.accumulo.core.client.TableExistsException;
import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.rya.indexing.StatementConstraints;
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.apache.rya.indexing.mongodb.temporal.MongoTemporalIndexer;
import org.apache.rya.mongodb.MongoDBRdfConfiguration;
import org.apache.rya.mongodb.MongoITBase;
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.Test;

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.MongoSecurityException;

/**
 * JUnit tests for TemporalIndexer and it's implementation MongoTemporalIndexer
 *
 * If you enjoy this test, please read RyaTemporalIndexerTest and YagoKBTest, which contain
 * many example SPARQL queries and updates and attempts to test independently of Mongo:
 *
 *     extras/indexingSail/src/test/java/org.apache/rya/indexing/Mongo/RyaTemporalIndexerTest.java
 *     {@link org.apache.rya.indexing.Mongo.RyaTemporalIndexerTest}
 *     {@link org.apache.rya.indexing.Mongo.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.
 *
 */
public final class MongoTemporalIndexerIT extends MongoITBase {

    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 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(final 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.
        final ValueFactory vf = SimpleValueFactory.getInstance();
        final 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()));
        }
    }

    @Override
    protected void updateConfiguration(final MongoDBRdfConfiguration conf) {
        // This is 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);
    }

    /**
     * Test method for {@link MongoTemporalIndexer#storeStatement(convertStatement(org.eclipse.rdf4j.model.Statement)}
     */
    @Test
    public void testStoreStatement() throws IOException {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            final ValueFactory vf = SimpleValueFactory.getInstance();

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

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

            final String invalidDateString = "ThisIsAnInvalidDate";
            tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj2"), pred1_atTime, vf.createLiteral(invalidDateString))));

            // 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.
            final Statement s3 = vf.createStatement(vf.createIRI("foo:subj3"), pred1_atTime, vf.createLiteral(testDate2014InBRST));
            final Statement s4 = vf.createStatement(vf.createIRI("foo:subj4"), pred2_circa, vf.createLiteral(testDate2016InET));
            tIndexer.storeStatement(convertStatement(s3));
            tIndexer.storeStatement(convertStatement(s4));

            // 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"))));

            printTables(tIndexer, "junit testing: Temporal entities stored in testStoreStatement");
            assertEquals(2, tIndexer.getCollection().find().count());
        }
    }

    @Test
    public void testDelete() throws IOException, MongoException, TableNotFoundException, TableExistsException, NoSuchAlgorithmException {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            final ValueFactory vf = SimpleValueFactory.getInstance();

            final IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);
            final 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.
            final Statement s1 = vf.createStatement(vf.createIRI("foo:subj3"), pred1_atTime, vf.createLiteral(testDate2014InBRST));
            final Statement s2 = vf.createStatement(vf.createIRI("foo:subj4"), pred2_circa, vf.createLiteral(testDate2016InET));
            tIndexer.storeStatement(convertStatement(s1));
            tIndexer.storeStatement(convertStatement(s2));

            final String dbName = conf.getMongoDBName();
            final DB db = super.getMongoClient().getDB(dbName);
            DBCollection collection = db.getCollection(conf.get(MongoDBRdfConfiguration.MONGO_COLLECTION_PREFIX, "rya") + tIndexer.getCollectionName());

            printTables(tIndexer, "junit testing: Temporal entities stored in testDelete before delete");
            assertEquals("Number of rows stored.", 2, collection.count()); // 4 index entries per statement

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

            printTables(tIndexer, "junit testing: Temporal entities stored in testDelete after delete");
            assertEquals("Number of rows stored after delete.", 0, collection.count());
        }
    }

    /**
     * Test instant after a given instant.
     * From the series: instant {equal, before, after} instant
     * @throws MongoSecurityException
     * @throws MongoException
     * @throws TableNotFoundException
     */
    @Test
    public void testQueryInstantAfterInstant() throws IOException, QueryEvaluationException, TableNotFoundException, MongoException {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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.
            final int searchForSeconds = 4;
            final int expectedResultCount = 9;
            for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here
                tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            }

            CloseableIteration<Statement, QueryEvaluationException> iter;
            iter = tIndexer.queryInstantAfterInstant(seriesTs[searchForSeconds], EMPTY_CONSTRAINTS);
            int count = 0;
            while (iter.hasNext()) {
                final Statement s = iter.next();
                final Statement nextExpectedStatement = seriesSpo[searchForSeconds + count + 1]; // <== logic here
                assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
                count++;
            }
            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 {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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.
            final int searchForSeconds = 4;
            final int expectedResultCount = 4;
            for (int s = 0; s <= searchForSeconds + 15; s++) { // <== logic here
                tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            }

            CloseableIteration<Statement, QueryEvaluationException> iter;

            iter = tIndexer.queryInstantBeforeInstant(seriesTs[searchForSeconds], EMPTY_CONSTRAINTS);
            int count = 0;
            while (iter.hasNext()) {
                final Statement s = iter.next();
                final Statement nextExpectedStatement = seriesSpo[count]; // <== logic here
                assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
                count++;
            }
            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 {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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.
            final TemporalInterval searchForSeconds = tvB02_E31;
            final int expectedResultCount = 2; // 00 and 01 seconds.
            for (int s = 0; s <= 40; s++) { // <== logic here
                tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            }

            CloseableIteration<Statement, QueryEvaluationException> iter;
            iter = tIndexer.queryInstantBeforeInterval(searchForSeconds, EMPTY_CONSTRAINTS);
            int count = 0;
            while (iter.hasNext()) {
                final Statement s = iter.next();
                final Statement nextExpectedStatement = seriesSpo[count]; // <== logic here
                assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
                count++;
            }
            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 {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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.
            final TemporalInterval searchAfterInterval = tvB02_E31; // from 2 to 31 seconds
            final int endingSeconds = 31;
            final int expectedResultCount = 9; // 32,33,...,40 seconds.
            for (int s = 0; s <= endingSeconds + expectedResultCount; s++) { // <== logic here
                tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            }

            CloseableIteration<Statement, QueryEvaluationException> iter;
            iter = tIndexer.queryInstantAfterInterval(searchAfterInterval, EMPTY_CONSTRAINTS);
            int count = 0;
            while (iter.hasNext()) {
                final Statement s = iter.next();
                final Statement nextExpectedStatement = seriesSpo[count + endingSeconds + 1]; // <== logic here
                assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
                count++;
            }
            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 {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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.
            final TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds
            final int beginningSeconds = 2; // <== logic here, and next few lines.
            final int endingSeconds = 31;
            final int expectedResultCount = endingSeconds - beginningSeconds - 1; // 3,4,...,30 seconds.
            for (int s = 0; s <= 40; s++) {
                tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            }

            CloseableIteration<Statement, QueryEvaluationException> iter;
            iter = tIndexer.queryInstantInsideInterval(searchInsideInterval, EMPTY_CONSTRAINTS);
            int count = 0;
            while (iter.hasNext()) {
                final Statement s = iter.next();
                final Statement nextExpectedStatement = seriesSpo[count + beginningSeconds + 1]; // <== logic here
                assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
                count++;
            }
            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 {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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.
            final TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds
            final int searchSeconds = 2; // <== logic here, and next few lines.
            final int expectedResultCount = 1; // 2 seconds.
            for (int s = 0; s <= 10; s++) {
                tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            }

            CloseableIteration<Statement, QueryEvaluationException> iter;
            iter = tIndexer.queryInstantHasBeginningInterval(searchInsideInterval, EMPTY_CONSTRAINTS);
            int count = 0;
            while (iter.hasNext()) {
                final Statement s = iter.next();
                final Statement nextExpectedStatement = seriesSpo[searchSeconds]; // <== logic here
                assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s));
                count++;
            }
            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 {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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.
            final TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds
            final int searchSeconds = 31; // <== logic here, and next few lines.
            final int expectedResultCount = 1; // 31 seconds.
            for (int s = 0; s <= 40; s++) {
                tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            }

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

    /**
     * Test method for
     * {@link org.apache.rya.indexing.Mongo.temporal.MongoTemporalIndexer#queryIntervalEquals(TemporalInterval, StatementConstraints)}
     * .
     * @throws IOException
     * @throws QueryEvaluationException
     *
     */
    @Test
    public void testQueryIntervalEquals() throws IOException, QueryEvaluationException {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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


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

    /**
     * Test interval before a given interval, for method:
     * {@link MongoTemporalIndexer#queryIntervalBefore(TemporalInterval, StatementConstraints)}.
     *
     * @throws IOException
     * @throws QueryEvaluationException
     */
    @Test
    public void testQueryIntervalBefore() throws IOException, QueryEvaluationException {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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]));


            CloseableIteration<Statement, QueryEvaluationException> iter;
            iter = tIndexer.queryIntervalBefore(tvB02_E31, EMPTY_CONSTRAINTS);
            // Should be found twice:
            assertTrue("spo_B00_E01 should be found, but actually returned empty results. spo_B00_E01=" + spo_B00_E01, iter.hasNext());
            assertTrue("spo_B00_E01 should be found, but found another.", spo_B00_E01.equals(iter.next()));
            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 MongoTemporalIndexer#queryIntervalAfter(TemporalInterval, StatementContraints).
     *
     * @throws IOException
     * @throws QueryEvaluationException
     */
    @Test
    public void testQueryIntervalAfter() throws IOException, QueryEvaluationException {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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]));

            CloseableIteration<Statement, QueryEvaluationException> iter;
            iter = tIndexer.queryIntervalAfter(tvB02_E29, EMPTY_CONSTRAINTS);
            // Should be found twice:
            assertTrue("spo_B30_E32 should be found, but actually returned empty results. spo_B30_E32=" + spo_B30_E32, iter.hasNext());
            final Statement s = iter.next();
            assertTrue("spo_B30_E32 should be found, but found another. spo_B30_E32="+spo_B30_E32+", but found="+s, spo_B30_E32.equals(s));
            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 {
        try(MongoTemporalIndexer tIndexer = new MongoTemporalIndexer()) {
            tIndexer.setConf(conf);
            tIndexer.init();

            // 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.
            final int searchForSeconds = 4;
            final int expectedResultCount = 9;
            for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here
                tIndexer.storeStatement(convertStatement(seriesSpo[s]));
            }
            final ValueFactory vf = SimpleValueFactory.getInstance();
            final IRI pred3_CIRCA_ = vf.createIRI(URI_PROPERTY_CIRCA);  // this one to ignore.
            final IRI pred2_eventTime = vf.createIRI(URI_PROPERTY_EVENT_TIME);
            final IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME);

            // add the predicate = EventTime ; Store in an array for verification.
            final Statement[] SeriesTs_EventTime = new Statement[expectedResultCount+1];
            for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here
                final 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
                final Statement statement = vf.createStatement(vf.createIRI("foo:CircaEventSubj0" + s), pred3_CIRCA_, vf.createLiteral(seriesTs[s].getAsReadable()));
                tIndexer.storeStatement(convertStatement(statement));
            }

            CloseableIteration<Statement, QueryEvaluationException> iter;
            final StatementConstraints constraints = new StatementConstraints();
            constraints.setPredicates(new HashSet<>(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()) {
                final Statement s = iter.next();
                final 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);
                }

            }

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

    /**
     * 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.
     * @throws IOException
     */
    public void printTables(MongoTemporalIndexer tIndexer, final String description) throws IOException {
        System.out.println("-- start printTables() -- " + description);
        System.out.println("Reading : " + tIndexer.getCollection().getFullName());
        final DBCursor cursor = tIndexer.getCollection().find();
        while(cursor.hasNext()) {
            final DBObject dbo = cursor.next();
            System.out.println(dbo.toString());
        }
        System.out.println();
    }
}
