com.barchart.feed.ddf.resolver.provider.ResolverDDF.java Source code

Java tutorial

Introduction

Here is the source code for com.barchart.feed.ddf.resolver.provider.ResolverDDF.java

Source

/**
 * Copyright (C) 2011-2012 Barchart, Inc. <http://www.barchart.com/>
 *
 * All rights reserved. Licensed under the OSI BSD License.
 *
 * http://www.opensource.org/licenses/bsd-license.php
 */
package com.barchart.feed.ddf.resolver.provider;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.barchart.feed.api.model.meta.Instrument;
import com.barchart.feed.base.thread.ExecutorCallable;
import com.barchart.feed.base.values.api.TextValue;
import com.barchart.feed.ddf.resolver.api.DDF_Resolver;

// TODO: Auto-generated Javadoc
class ResolverDDF extends ResolverState implements DDF_Resolver {

    static final double RAM_BUFFER_SIZE_MB = 48.0;

    private static Logger log = LoggerFactory.getLogger(ResolverDDF.class);

    //

    private final ExecutorCallable executor;
    private final String folder;
    private final Analyzer analyzer;
    private final int limit;

    //

    private Directory directory;

    //

    ResolverDDF(final ExecutorCallable executor, final String folder, final int limit) {

        this.executor = executor;
        this.folder = folder;
        this.limit = limit;
        this.analyzer = new StandardAnalyzer(ConstResolver.VERSION);

    }

    private synchronized Directory getDirectory() throws Exception {

        if (directory == null) {

            final File file = new File(folder);

            directory = new SimpleFSDirectory(file);

        }

        return directory;

    }

    private IndexWriter writer;

    private synchronized IndexWriter getWriter() throws Exception {

        if (writer == null) {

            final IndexWriterConfig config = new IndexWriterConfig(ConstResolver.VERSION, analyzer);

            // config.setRAMBufferSizeMB(RAM_BUFFER_SIZE_MB);

            writer = new IndexWriter(getDirectory(), config);

            writer.commit();

        }

        return writer;

    }

    private final Future<?> futureNone = new FutureNone<Void>();

    private Future<?> future;

    /* (non-Javadoc)
     * @see com.barchart.feed.ddf.resolver.api.DDF_Resolver#open(com.barchart.feed.ddf.resolver.api.DDF_Resolver.Mode)
     */
    @Override
    public synchronized Future<?> open(final Mode mode) {

        if (isOpen()) {
            log.error("aready open");
            return futureNone;
        }

        try {
            getDirectory();
            getWriter();
            getSearcher();
        } catch (final Exception e) {
            log.error("can not open index", e);
            return futureNone;
        }

        //

        Status status;
        try {
            status = getStatus();
        } catch (final Exception e) {
            status = new Status(0, false);
        }

        final boolean isPending = status.isPending();

        //

        switch (mode) {
        default:
        case DEFAULT:
            if (isPending) {
                break;
            } else {
                return futureNone;
            }
        case REINDEX:
            log.info("index pending : {}", isPending);
            break;
        case REBUILD:
            try {
                delete();
                log.info("index deleted");
            } catch (final Exception e) {
                log.error("can not delete index", e);
            }
            break;
        }

        super.open();

        final Callable<Void> task = new TaskUpdate(searcher, writer);

        future = executor.submit(task);

        return future;

    }

    private void delete() throws Exception {

        final IndexWriterConfig config = new IndexWriterConfig(ConstResolver.VERSION, analyzer);

        final IndexWriter writer = new IndexWriter(getDirectory(), config);

        writer.deleteAll();

        writer.close();

    }

    /* (non-Javadoc)
     * @see com.barchart.feed.ddf.resolver.api.DDF_Resolver#searchLucene(java.lang.String)
     */
    @Override
    public List<Instrument> searchLucene(final String phrase) throws Exception {

        final Query query = new QueryParser(ConstResolver.VERSION, CodecHelper.FIELD_INST_BODY, analyzer)
                .parse(phrase);

        return searchInstrument(query);

    }

    /* (non-Javadoc)
     * @see com.barchart.feed.ddf.resolver.api.DDF_Resolver#searchSimple(java.lang.String)
     */
    @Override
    public List<Instrument> searchSimple(final String phrase) throws Exception {

        final Query query = CodecHelper.buildQuerySimple(phrase);

        return searchInstrument(query);

    }

    private IndexSearcher searcher;

    private synchronized IndexSearcher getSearcher() throws Exception {

        if (searcher == null) {
            searcher = new IndexSearcher(getDirectory(), true);
        }

        final IndexReader readerOld = searcher.getIndexReader();
        final IndexReader readerNew = readerOld.reopen(true);

        /** get new instance only when index is updated */
        if (readerNew != readerOld) {
            readerOld.close();
            searcher = new IndexSearcher(readerNew);
        }

        return searcher;

    }

    private List<Document> searchDocument(final Query query) throws Exception {

        final IndexSearcher searcher = getSearcher();

        final TopScoreDocCollector collector = TopScoreDocCollector.create(limit, true);

        searcher.search(query, collector);

        final ScoreDoc[] hits = collector.topDocs().scoreDocs;

        final int size = Math.min(hits.length, limit);

        log.debug("hits size : {}", size);

        final List<Document> list = new ArrayList<Document>(size);

        for (int k = 0; k < size; k++) {

            final int index = hits[k].doc;

            final Document doc = searcher.doc(index);

            list.add(doc);

        }

        return list;

    }

    private List<Instrument> searchInstrument(final Query query) throws Exception {

        final List<Document> listDocument = searchDocument(query);

        final List<Instrument> listInstrument = new ArrayList<Instrument>(listDocument.size());

        for (final Document doc : listDocument) {

            final Instrument instrument = CodecHelper.<TextValue>instrumentDecode(doc);

            listInstrument.add(instrument);

        }

        return listInstrument;

    }

    /* (non-Javadoc)
     * @see com.barchart.feed.ddf.resolver.provider.ResolverState#close()
     */
    @Override
    public synchronized void close() {

        if (isClosed()) {
            log.error("already closed");
            return;
        }

        if (future != null) {
            future.cancel(true);
            future = null;
        }

        if (searcher != null) {
            try {
                searcher.close();
            } catch (final Exception e) {
                log.error("", e);
            }
            searcher = null;
        }

        if (writer != null) {
            try {
                writer.close();
            } catch (final Exception e) {
                log.error("", e);
            }
            writer = null;
        }

        if (directory != null) {
            try {
                directory.close();
            } catch (final Exception e) {
                log.error("", e);
            }
            directory = null;
        }

        super.close();

    }

    Status getStatus() throws Exception {

        final Query query = new TermQuery(Status.TERM);

        final List<Document> list = searchDocument(query);

        if (list.size() == 0) {
            return Status.EMPTY;
        }

        final Document doc = list.get(0);

        final Status status = Status.decode(doc);

        return status;

    }

    void setStatus(final Status status) throws Exception {

        final Document doc = Status.encode(status);

        final IndexWriterConfig config = new IndexWriterConfig(ConstResolver.VERSION, analyzer);

        final IndexWriter writer = new IndexWriter(getDirectory(), config);

        writer.updateDocument(Status.TERM, doc);

        writer.close();

    }

}