Package in.partake.service.impl

Source Code of in.partake.service.impl.LuceneService

package in.partake.service.impl;

import in.partake.app.PartakeConfiguration;
import in.partake.base.TimeUtil;
import in.partake.model.dao.DAOException;
import in.partake.model.dto.auxiliary.EventCategory;
import in.partake.service.EventSearchServiceException;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryWrapperFilter;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import play.Logger;

/**
* @author shinyak
*/
public class LuceneService {
    private static volatile LuceneService instance;

    private IndexWriter indexWriter;
    private IndexReader indexReader;
    private IndexSearcher indexSearcher;
    private Analyzer analyzer;

    public static LuceneService get() {
        return instance;
    }

    public static void initialize() throws EventSearchServiceException {
        Logger.info("LuceneService is being initialized.");

        if (instance != null)
            return;
        instance = new LuceneService();
    }

    public static void destroy() throws EventSearchServiceException {
        Logger.info("LuceneService is being destructed.");
        if (instance == null)
            return;

        try {
            instance.cleanUp();
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }

        instance = null;
    }

    private LuceneService() {
        try {
            File indexDirFile = new File(PartakeConfiguration.luneceIndexDir());
            Directory indexDir = FSDirectory.open(indexDirFile);

            // create index.
            Analyzer luceneAnalyzer = new StandardAnalyzer(Version.LUCENE_30);
            indexWriter = new IndexWriter(indexDir, luceneAnalyzer, new IndexWriter.MaxFieldLength(1024*1024));
            indexReader = indexWriter.getReader();
            indexSearcher = new IndexSearcher(indexReader);
            analyzer = new CJKAnalyzer(Version.LUCENE_30);
        } catch (IOException e) {
            Logger.error("LuceneService cannot be initialized", e);
            indexWriter = null;
            indexReader = null;
            indexSearcher = null;
            analyzer = null;
        }
    }

    public void addDocument(Document doc) throws EventSearchServiceException {
        try {
            indexWriter.addDocument(doc, analyzer);
            indexWriter.commit();
            reset();
        } catch (CorruptIndexException e) {
            throw new EventSearchServiceException(e);
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    public void updateDocument(Document doc) throws EventSearchServiceException {
        try {
            indexWriter.updateDocument(new Term("ID", doc.get("ID")), doc, analyzer);
            indexWriter.commit();
            reset();
        } catch (CorruptIndexException e) {
            throw new EventSearchServiceException(e);
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    public void removeDocument(String id) throws EventSearchServiceException {
        try {
            indexWriter.deleteDocuments(new Term("ID", id));
            indexWriter.commit();
            reset();
        } catch (CorruptIndexException e) {
            throw new EventSearchServiceException(e);
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    public boolean hasDocument(String id) throws EventSearchServiceException {
        try {
            Query query = new TermQuery(new Term("ID", id));
            TopDocs docs = indexSearcher.search(query, 1);
            return docs.totalHits > 0;
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    public Document getDocument(int doc) throws EventSearchServiceException {
        try {
            return indexSearcher.doc(doc);
        } catch (CorruptIndexException e) {
            throw new EventSearchServiceException(e);
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    public TopDocs getRecentDocuments(int n) throws EventSearchServiceException {
        try {
            long current = new Date().getTime();
            Query query = new TermRangeQuery("DEADLINE-TIME", TimeUtil.getTimeString(current), TimeUtil.getTimeString(Long.MAX_VALUE), true, true);

            Sort sort = new Sort(new SortField("CREATED-AT", SortField.STRING, true));

            return indexSearcher.search(query, null, n, sort);
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    public TopDocs getRecentCategoryDocuments(String category, int maxDocument) throws EventSearchServiceException, IllegalArgumentException {
        if (!EventCategory.isValidCategoryName(category)) {
            throw new IllegalArgumentException("Unknown category");
        }
        Query query = new TermQuery(new Term("CATEGORY", category));
        Sort sort = new Sort(new SortField("CREATED-AT", SortField.STRING, true));
        try {
            return indexSearcher.search(query, null, maxDocument, sort);
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    public TopDocs search(String term, String category, String sortOrder, boolean beforeDeadlineOnly, int maxDocument) throws EventSearchServiceException, ParseException, IllegalArgumentException {
        try {
            Query query;
            if (StringUtils.isEmpty(term)) {
                // If the search term is not null, all events should be displayed.
                query = new MatchAllDocsQuery();
            } else {
                QueryParser partialParser = new QueryParser(Version.LUCENE_30, "CONTENT", analyzer);
                query = partialParser.parse(term);
            }

            // TODO: なんか汚い...。
            Filter filter;
            if (beforeDeadlineOnly) {
                long current = new Date().getTime();
                if (EventCategory.getAllEventCategory().equals(category) || "".equals(category)) {
                    Query filterQuery = new TermRangeQuery("DEADLINE-TIME", TimeUtil.getTimeString(current), TimeUtil.getTimeString(Long.MAX_VALUE), true, true);
                    filter = new QueryWrapperFilter(filterQuery);
                } else {
                    if (!EventCategory.isValidCategoryName(category)) {
                        throw new IllegalArgumentException("Unknown category");
                    }
                    BooleanQuery filterQuery = new BooleanQuery();
                    filterQuery.add(new BooleanClause(new TermQuery(new Term("CATEGORY", category)), Occur.MUST));
                    filterQuery.add(new BooleanClause(new TermRangeQuery("DEADLINE-TIME", TimeUtil.getTimeString(current), TimeUtil.getTimeString(Long.MAX_VALUE), true, true), Occur.MUST));
                    filter = new QueryWrapperFilter(filterQuery);
                }
            } else {
                if (EventCategory.getAllEventCategory().equals(category) || "".equals(category)) {
                    filter = null;
                    // filter = new QueryWrapperFilter(new MatchAllDocsQuery());
                } else {
                    if (!EventCategory.isValidCategoryName(category)) {
                        throw new IllegalArgumentException("Unknown category");
                    }
                    filter = new QueryWrapperFilter(new TermQuery(new Term("CATEGORY", category)));
                }
            }

            // TODO: このへんの定数なんとかするべき。いろんなところに散らばっていて使いにくい。

            Sort sort;
            if ("score".equals(sortOrder)) {
                sort = new Sort(SortField.FIELD_SCORE, new SortField("BEGIN-TIME", SortField.STRING));
            } else if ("createdAt".equals(sortOrder)) {
                sort = new Sort(new SortField("CREATED-AT", SortField.STRING, true));
            } else if ("deadline".equals(sortOrder)) {
                sort = new Sort(new SortField("DEADLINE-TIME", SortField.STRING));
            } else if ("deadline-r".equals(sortOrder)) {
                sort = new Sort(new SortField("DEADLINE-TIME", SortField.STRING, true));
            } else if ("beginDate".equals(sortOrder)) {
                sort = new Sort(new SortField("BEGIN-TIME", SortField.STRING));
            } else if ("beginDate-r".equals(sortOrder)) {
                sort = new Sort(new SortField("BEGIN-TIME", SortField.STRING, true));
            } else {
                // 決まってない場合は、score 順にする。
                sort = new Sort(SortField.FIELD_SCORE, new SortField("BEGIN-TIME", SortField.STRING));
            }

            return indexSearcher.search(query, filter, maxDocument, sort);
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    /**
    * Lucene index を全て捨てる
    * @throws DAOException
    */
    public void truncate() throws EventSearchServiceException {
        try {
           indexWriter.deleteAll();
           indexWriter.commit();
           reset();
        } catch (CorruptIndexException e) {
            throw new EventSearchServiceException(e);
        } catch (IOException e) {
            throw new EventSearchServiceException(e);
        }
    }

    private void cleanUp() throws IOException {
        if (indexWriter != null)
            indexWriter.close();
        if (indexReader != null)
            indexReader.close();
        if (indexSearcher != null)
            indexSearcher.close();
    }

    /**
     * When index is changed, reset() should be called.
     */
    private synchronized void reset() {
        try {
            IndexReader oldReader = indexReader;
            indexReader = indexWriter.getReader();
            indexSearcher = new IndexSearcher(indexReader);

            if (oldReader != indexReader)
                oldReader.close();
        } catch (IOException e) {
            throw new RuntimeException(e); // TODO: Is this OK?
        }
    }
}
TOP

Related Classes of in.partake.service.impl.LuceneService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.