/*
 * 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.jackrabbit.oak.plugins.index.lucene;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.google.common.collect.ImmutableList;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.commons.CIHelper;
import org.apache.jackrabbit.oak.plugins.blob.datastore.CachingFileDataStore;
import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore;
import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreUtils;
import org.apache.jackrabbit.oak.plugins.index.CompositeIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.IndexEditor;
import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
import org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexCopier;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexTracker;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexDefinition;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexNode;
import org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakDirectory;
import org.apache.jackrabbit.oak.plugins.index.lucene.writer.MultiplexersLucene;
import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.search.ExtractedTextCache;
import org.apache.jackrabbit.oak.plugins.index.search.FieldNames;
import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants;
import org.apache.jackrabbit.oak.plugins.index.search.IndexDefinition;
import org.apache.jackrabbit.oak.plugins.index.search.IndexFormatVersion;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.DefaultEditor;
import org.apache.jackrabbit.oak.spi.commit.Editor;
import org.apache.jackrabbit.oak.spi.commit.EditorHook;
import org.apache.jackrabbit.oak.spi.mount.Mount;
import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.mount.Mounts;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
import org.apache.jackrabbit.test.ISO8601;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import static com.google.common.collect.ImmutableSet.of;
import static javax.jcr.PropertyType.TYPENAME_STRING;
import static org.apache.jackrabbit.oak.InitialContentHelper.INITIAL_CONTENT;
import static org.apache.jackrabbit.oak.api.Type.STRINGS;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.VERSION;
import static org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.newLuceneIndexDefinitionV2;
import static org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLuceneIndexDefinition;
import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.INCLUDE_PROPERTY_NAMES;
import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;

@RunWith(Parameterized.class)
public class LuceneIndexEditorTest {
    private EditorHook HOOK;

    private NodeState root = INITIAL_CONTENT;

    private NodeBuilder builder = root.builder();

    private IndexTracker tracker = new IndexTracker();

    private LuceneIndexNode indexNode;

    @Rule
    public final TemporaryFolder temporaryFolder = new TemporaryFolder(new File("target"));

    @Parameterized.Parameter
    public boolean useBlobStore;

    @Parameterized.Parameters(name = "{index}: useBlobStore ({0})")
    public static List<Boolean[]> fixtures() {
        return ImmutableList.of(new Boolean[] {true}, new Boolean[] {false});
    }

    @Before
    public void setup() throws Exception {
        if (useBlobStore) {
            LuceneIndexEditorProvider provider = new LuceneIndexEditorProvider();
            CachingFileDataStore ds = DataStoreUtils
                .createCachingFDS(temporaryFolder.newFolder().getAbsolutePath(),
                    temporaryFolder.newFolder().getAbsolutePath());
            provider.setBlobStore(new DataStoreBlobStore(ds));
            HOOK = new EditorHook(new IndexUpdateProvider(provider));
        } else {
            HOOK = new EditorHook(new IndexUpdateProvider(new LuceneIndexEditorProvider()));
        }
    }

    @Test
    public void testLuceneWithFullText() throws Exception {
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder idxnb = newLuceneIndexDefinitionV2(index, "lucene",
                of(TYPENAME_STRING));
        LuceneIndexDefinition defn = new LuceneIndexDefinition(root, idxnb.getNodeState(), "/foo");
        NodeState before = builder.getNodeState();
        builder.child("test").setProperty("foo", "fox is jumping");
        builder.child("test").setProperty("price", 100);
        NodeState after = builder.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);

        //system fields starts with ':' so need to be escaped
        assertEquals("/test", query(escape(FieldNames.createAnalyzedFieldName("foo"))+":fox", defn));
        assertNull("Non string properties not indexed by default",
                getPath(NumericRangeQuery.newLongRange("price", 100L, 100L, true, true)));
    }

    @Test
    public void noChangeIfNonIndexedDelete() throws Exception{
        NodeState before = builder.getNodeState();
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene", of(TYPENAME_STRING));
        nb.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
        nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo"), STRINGS));


        builder.child("test").setProperty("foo", "bar");
        builder.child("test").child("a");
        NodeState after = builder.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);
        assertEquals("/test", getPath(new TermQuery(new Term("foo", "bar"))));

        NodeState luceneIdxState1 = NodeStateUtils.getNode(indexed, "/oak:index/lucene");

        before = indexed;
        builder = indexed.builder();
        builder.getChildNode("test").getChildNode("a").remove();
        after = builder.getNodeState();
        indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);

        NodeState luceneIdxState2 = NodeStateUtils.getNode(indexed, "/oak:index/lucene");
        assertEquals(luceneIdxState1, luceneIdxState2);
    }

    private String escape(String name) {
        return name.replace(":", "\\:");
    }

    @Test
    public void testLuceneWithNonFullText() throws Exception {
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene",
                of(TYPENAME_STRING));
        nb.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
        nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo", "price", "weight", "bool", "creationTime"), STRINGS));
        LuceneIndexDefinition defn = new LuceneIndexDefinition(root, nb.getNodeState(), "/foo");
        NodeState before = builder.getNodeState();
        builder.child("test").setProperty("foo", "fox is jumping");
        builder.child("test").setProperty("bar", "kite is flying");
        builder.child("test").setProperty("price", 100);
        builder.child("test").setProperty("weight", 10.0);
        builder.child("test").setProperty("bool", true);
        builder.child("test").setProperty("truth", true);
        builder.child("test").setProperty("creationTime", createCal("05/06/2014"));
        NodeState after = builder.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);

        assertNull("Fulltext search should not work", query("foo:fox",defn));
        assertEquals("/test", getPath(new TermQuery(new Term("foo", "fox is jumping"))));
        assertNull("bar must NOT be indexed", getPath(new TermQuery(new Term("bar", "kite is flying"))));

        //Long
        assertEquals("/test", getPath(NumericRangeQuery.newDoubleRange("weight", 8D, 12D, true, true)));

        //Double
        assertEquals("/test", getPath(NumericRangeQuery.newLongRange("price", 100L, 100L, true, true)));

        //Boolean
        assertEquals("/test", getPath(new TermQuery(new Term("bool", "true"))));
        assertNull("truth must NOT be indexed", getPath(new TermQuery(new Term("truth", "true"))));

        //Date
        assertEquals("/test", getPath(NumericRangeQuery.newLongRange("creationTime",
                dateToTime("05/05/2014"), dateToTime("05/07/2014"), true, true)));
    }

    @Test
    public void noOfDocsIndexedNonFullText() throws Exception {
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene",
                of(TYPENAME_STRING));
        nb.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
        nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo"), STRINGS));

        NodeState before = builder.getNodeState();
        builder.child("test").setProperty("foo", "fox is jumping");
        builder.child("test2").setProperty("bar", "kite is flying");
        builder.child("test3").setProperty("foo", "wind is blowing");
        NodeState after = builder.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);

        assertEquals(2, getSearcher().getIndexReader().numDocs());
    }

    @Test
    public void saveDirectoryListing() throws Exception {
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene",
            of(TYPENAME_STRING));
        nb.setProperty(LuceneIndexConstants.SAVE_DIR_LISTING, true);
        nb.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
        nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo"), STRINGS));

        NodeState before = builder.getNodeState();
        builder.child("test").setProperty("foo", "fox is jumping");
        NodeState after = builder.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        NodeState dir = indexed.getChildNode("oak:index").getChildNode("lucene").getChildNode(":data");
        assertTrue(dir.hasProperty(OakDirectory.PROP_DIR_LISTING));
    }

    /**
     * 1. Index property foo in /test
     * 2. Then modify some other property in /test
     *
     * This should not cause the index to be updated
     */
    @Test
    public void nonIncludedPropertyChange() throws Exception {
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene",
                of(TYPENAME_STRING));
        nb.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
        nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo"),
                STRINGS));

        NodeState before = builder.getNodeState();
        builder.child("test").setProperty("foo", "fox is jumping");
        builder.child("test2").setProperty("foo", "bird is chirping");
        NodeState after = builder.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);

        assertEquals(2, getSearcher().getIndexReader().numDocs());

        assertEquals("/test", getPath(new TermQuery(new Term("foo", "fox is jumping"))));

        releaseIndexNode();
        before = indexed;
        builder = before.builder();
        builder.child("test").setProperty("bar", "kite is flying");
        after = builder.getNodeState();
        indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);

        assertEquals(2, getSearcher().getIndexReader().numDocs());
        assertEquals("change in non included property should not cause " +
                "index update",0, getSearcher().getIndexReader().numDeletedDocs());
    }

    @Test
    public void testLuceneWithRelativeProperty() throws Exception {
        // OAK-6833
        assumeFalse(CIHelper.windows());

        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene",
                of(TYPENAME_STRING));
        nb.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
        nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo", "jcr:content/mime",
                "jcr:content/metadata/type"), STRINGS));

        NodeState before = builder.getNodeState();
        builder.child("test").setProperty("foo", "fox is jumping");
        builder.child("test").child("jcr:content").setProperty("mime", "text");
        builder.child("test").child("jcr:content").child("metadata").setProperty("type", "image");
        builder.child("jcr:content").setProperty("count", "text");
        builder.child("jcr:content").child("boom").child("metadata").setProperty("type", "image");
        NodeState after = builder.getNodeState();

        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);

        assertEquals(1, getSearcher().getIndexReader().numDocs());

        assertEquals("/test", getPath(new TermQuery(new Term("foo", "fox is jumping"))));
        assertEquals("/test", getPath(new TermQuery(new Term("jcr:content/mime", "text"))));
        assertEquals("/test", getPath(new TermQuery(new Term("jcr:content/metadata/type", "image"))));
        assertNull("bar must NOT be indexed", getPath(new TermQuery(new Term("count", "text"))));

        releaseIndexNode();
        before = indexed;
        builder = before.builder();
        builder.child("test").child("jcr:content").setProperty("mime", "pdf");
        after = builder.getNodeState();
        indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);

        assertEquals("/test", getPath(new TermQuery(new Term("jcr:content/mime", "pdf"))));

        releaseIndexNode();
        before = indexed;
        builder = before.builder();
        builder.child("test").child("jcr:content").remove();
        after = builder.getNodeState();
        indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);
        assertNull("removes must be persisted too, 1st level",
                getPath(new TermQuery(new Term("jcr:content/mime", "pdf"))));
        assertNull("removes must be persisted too, 2nd level",
                getPath(new TermQuery(new Term("jcr:content/metadata/type",
                        "image"))));
    }

    @Test
    public void indexVersionSwitchOnReindex() throws Exception{
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinition(index, "lucene",
                of(TYPENAME_STRING));

        //1. Trigger a index so that next index step does not see it as a fresh index
        NodeState indexed = HOOK.processCommit(EMPTY_NODE, builder.getNodeState(), CommitInfo.EMPTY);
        builder = indexed.builder();

        //By default logic would use current version. To simulate upgrade we forcefully set
        //version to V1
        builder.child(INDEX_DEFINITIONS_NAME).child("lucene").setProperty(IndexDefinition.INDEX_VERSION,
                IndexFormatVersion.V1.getVersion());

        NodeState before = builder.getNodeState();
        builder.child("test").setProperty("foo", "fox is jumping");
        NodeState after = builder.getNodeState();

        indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        assertEquals(IndexFormatVersion.V1, new IndexDefinition(root,
                indexed.getChildNode(INDEX_DEFINITIONS_NAME).getChildNode("lucene"), "/foo").getVersion());

        //3. Trigger a reindex and version should switch to current
        builder = indexed.builder();
        before = indexed;
        builder.child(INDEX_DEFINITIONS_NAME).child("lucene").setProperty(IndexConstants.REINDEX_PROPERTY_NAME, true);
        after = builder.getNodeState();
        indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        assertEquals(IndexFormatVersion.getDefault(), new IndexDefinition(root,
                indexed.getChildNode(INDEX_DEFINITIONS_NAME).getChildNode("lucene"), "/foo").getVersion());

    }

    @Test
    public void autoFormatUpdate() throws Exception{
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene",
                of(TYPENAME_STRING));

        //1. Trigger a index so that next index step does not see it as a fresh index
        NodeState indexed = HOOK.processCommit(EMPTY_NODE, builder.getNodeState(), CommitInfo.EMPTY);

        IndexDefinition defn = new IndexDefinition(root, indexed.getChildNode(INDEX_DEFINITIONS_NAME).getChildNode("lucene"), "/foo");
        assertFalse(defn.isOfOldFormat());
    }

    @Test
    public void copyOnWriteAndLocks() throws Exception {
        assumeFalse(CIHelper.windows());

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        IndexCopier copier = new IndexCopier(executorService, temporaryFolder.getRoot());

        FailOnDemandEditorProvider failingProvider = new FailOnDemandEditorProvider();
        EditorHook hook = new EditorHook(
                new IndexUpdateProvider(
                        new CompositeIndexEditorProvider(
                                failingProvider,
                                new LuceneIndexEditorProvider(copier))));

        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene", of(TYPENAME_STRING));
        IndexUtils.createIndexDefinition(index, "failingIndex", false, false, of("foo"), null);


        //1. Get initial set indexed. So that next cycle is normal indexing
        NodeState indexed = hook.processCommit(EMPTY_NODE, builder.getNodeState(), CommitInfo.EMPTY);
        builder = indexed.builder();

        NodeState before = indexed;
        builder.child("test").setProperty("a", "fox is jumping");
        NodeState after = builder.getNodeState();

        //2. Ensure that Lucene gets triggered but close is not called
        failingProvider.setShouldFail(true);
        try {
            hook.processCommit(before, after, CommitInfo.EMPTY);
            fail();
        } catch (CommitFailedException ignore){

        }

        //3. Disable the troubling editor
        failingProvider.setShouldFail(false);

        //4. Now commit should process fine
        hook.processCommit(before, after, CommitInfo.EMPTY);

        executorService.shutdown();
    }


    @Test
    public void multiplexingWriter() throws Exception{
        newLucenePropertyIndex("lucene", "foo");
        MountInfoProvider mip = Mounts.newBuilder()
                .mount("foo", "/libs", "/apps").build();
        EditorHook hook = new EditorHook(
                new IndexUpdateProvider(
                        new LuceneIndexEditorProvider(null, new ExtractedTextCache(0, 0), null, mip)));

        NodeState indexed = hook.processCommit(EMPTY_NODE, builder.getNodeState(), CommitInfo.EMPTY);
        builder = indexed.builder();
        NodeState before = indexed;
        builder.child("content").child("en").setProperty("foo", "bar");
        builder.child("libs").child("install").setProperty("foo", "bar");
        NodeState after = builder.getNodeState();

        indexed = hook.processCommit(before, after, CommitInfo.EMPTY);
        builder = indexed.builder();

        assertEquals(1, numDocs(mip.getMountByName("foo")));
        assertEquals(1, numDocs(mip.getDefaultMount()));
    }

    private int numDocs(Mount m) throws IOException {
        String indexDirName = MultiplexersLucene.getIndexDirName(m);
        NodeBuilder defnBuilder = builder.child(INDEX_DEFINITIONS_NAME).child("lucene");
        Directory d = new OakDirectory(defnBuilder, indexDirName, new LuceneIndexDefinition(root, defnBuilder.getNodeState(), "/foo"), true);
        IndexReader r = DirectoryReader.open(d);
        return r.numDocs();
    }


    //@Test
    public void checkLuceneIndexFileUpdates() throws Exception{
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinition(index, "lucene",
                of(TYPENAME_STRING));
        nb.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
        nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , "bar", "baz"), STRINGS));
        //nb.removeProperty(REINDEX_PROPERTY_NAME);

        NodeState before = builder.getNodeState();
        builder.child("test").setProperty("foo", "fox is jumping");

        //InfoStream.setDefault(new PrintStreamInfoStream(System.out));
        before = commitAndDump(before, builder.getNodeState());

        builder = before.builder();
        builder.child("test2").setProperty("bar", "ship is sinking");
        before = commitAndDump(before, builder.getNodeState());

        builder = before.builder();
        builder.child("test3").setProperty("baz", "horn is blowing");
        before = commitAndDump(before, builder.getNodeState());

        builder = before.builder();
        builder.child("test2").remove();
        before = commitAndDump(before, builder.getNodeState());

        builder = before.builder();
        builder.child("test2").setProperty("bar", "ship is back again");
        before = commitAndDump(before, builder.getNodeState());
    }

    @After
    public void releaseIndexNode(){
        if(indexNode != null){
            indexNode.release();
        }
        indexNode = null;
    }

    private NodeState newLucenePropertyIndex(String indexName, String propName){
        NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
        NodeBuilder nb = newLuceneIndexDefinitionV2(index, indexName,
                of(TYPENAME_STRING));
        nb.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
        nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of(propName), STRINGS));
        return builder.getNodeState();
    }

    private String query(String query, LuceneIndexDefinition defn) throws IOException, ParseException {
        QueryParser queryParser = new QueryParser(VERSION, "", defn.getAnalyzer());
        return getPath(queryParser.parse(query));
    }

    private String getPath(Query query) throws IOException {
        TopDocs td = getSearcher().search(query, 100);
        if (td.totalHits > 0){
            if(td.totalHits > 1){
                fail("More than 1 result found for query " + query);
            }
            return getSearcher().getIndexReader().document(td.scoreDocs[0].doc).get(FieldNames.PATH);
        }
        return null;
    }

    private IndexSearcher getSearcher(){
        if(indexNode == null){
            indexNode = tracker.acquireIndexNode("/oak:index/lucene");
        }
        return indexNode.getSearcher();
    }

    private NodeState commitAndDump(NodeState before, NodeState after) throws CommitFailedException, IOException {
        NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
        tracker.update(indexed);
        dumpIndexDir();
        return indexed;
    }

    private void dumpIndexDir() throws IOException {
        Directory dir = ((DirectoryReader)getSearcher().getIndexReader()).directory();

        System.out.println("================");
        String[] fileNames = dir.listAll();
        Arrays.sort(fileNames);
        for (String file : fileNames){
            System.out.printf("%s - %d %n", file, dir.fileLength(file));
        }
        releaseIndexNode();
    }

    public static Calendar createCal(String dt) throws java.text.ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        Calendar cal = Calendar.getInstance();
        cal.setTime(sdf.parse(dt));
        return cal;
    }

    static long dateToTime(String dt) throws java.text.ParseException {
        return FieldFactory.dateToLong(ISO8601.format(createCal(dt)));
    }

    private static class FailOnDemandEditorProvider implements IndexEditorProvider {

        private boolean shouldFail;

        @Override
        public Editor getIndexEditor(@NotNull String type, @NotNull NodeBuilder definition,
                                     @NotNull NodeState root,
                                     @NotNull IndexUpdateCallback callback) throws CommitFailedException {
            if (PropertyIndexEditorProvider.TYPE.equals(type)) {
                return new FailOnDemandEditor();
            }
            return null;
        }

        public void setShouldFail(boolean shouldFail) {
            this.shouldFail = shouldFail;
        }

        private class FailOnDemandEditor extends DefaultEditor implements IndexEditor {
            @Override
            public void leave(NodeState before, NodeState after)
                    throws CommitFailedException {
                throwExceptionIfTold();
                super.leave(before, after);
            }

            void throwExceptionIfTold() throws CommitFailedException {
                if (shouldFail) {
                    throw new CommitFailedException("commit",1 , null);
                }
            }
        }
    }

}
