com.isotrol.impe3.oi.dao.impl.IndexDAOImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.isotrol.impe3.oi.dao.impl.IndexDAOImpl.java

Source

/**
 * This file is part of Port@l
 * Port@l 3.0 - Portal Engine and Management System
 * Copyright (C) 2010  Isotrol, SA.  http://www.isotrol.com
 *
 * Port@l is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Port@l is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Port@l.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.isotrol.impe3.oi.dao.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.derquinse.lucis.IndexNotAvailableException;
import net.sf.derquinse.lucis.Page;
import net.sf.lucis.core.DocMapper;
import net.sf.lucis.core.Factory;
import net.sf.lucis.core.LucisQuery;
import net.sf.lucis.core.Queryable;
import net.sf.lucis.core.Store;
import net.sf.lucis.core.support.Queryables;

import org.apache.lucene.analysis.Analyzer;
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.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
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.WildcardQuery;
import org.springframework.beans.factory.InitializingBean;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.isotrol.impe3.dto.OrderDTO;
import com.isotrol.impe3.dto.PageDTO;
import com.isotrol.impe3.dto.PageFilter;
import com.isotrol.impe3.dto.StringFilterDTO;
import com.isotrol.impe3.dto.StringMatchMode;
import com.isotrol.impe3.oi.api.InterviewFilterDTO;
import com.isotrol.impe3.oi.api.InterviewSelDTO;
import com.isotrol.impe3.oi.dao.IndexDAO;
import com.isotrol.impe3.oi.mappers.InterviewSelDTODocMapper;
import com.isotrol.impe3.oi.server.InterviewSchema;

/**
 * Index DAO implementation
 * @author Emilio Escobar Reyero
 */
// @Repository
public class IndexDAOImpl implements IndexDAO, InitializingBean {

    /** Store */
    // @Autowired
    private Store<Long> store;
    /** Queryable. */
    private Queryable queryable;
    /** Analyzer. */
    // @Autowired
    private Analyzer analyzer;

    /** Lucene max clause count. */
    private int maxClauseCount = 2048;

    public PageDTO<InterviewSelDTO> findInterviews(PageFilter<InterviewFilterDTO> filter) {
        final Query q = filterInterviewMapper.apply(filter);

        final Sort s = orderings(filter.getOrderings());

        final DocMapper<InterviewSelDTO> mapper = new InterviewSelDTODocMapper();
        final LucisQuery<Page<InterviewSelDTO>> lq = LucisQuery.page(q, null, s, mapper,
                filter.getPagination().getFirst(), filter.getPagination().getSize());

        Page<InterviewSelDTO> page;
        try {
            page = queryable.query(lq);
        } catch (IndexNotAvailableException e) {
            page = Page.<InterviewSelDTO>empty();
        }

        return pageInterviewMapper.apply(page);
    }

    /**
     * Sets lucene boolean query max clause count.
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    public void afterPropertiesSet() throws Exception {
        queryable = Queryables.simple(store);
        BooleanQuery.setMaxClauseCount(maxClauseCount);
    }

    private Sort orderings(List<OrderDTO> orders) {
        if (orders == null || orders.isEmpty()) {
            return null;
        }

        SortField[] fields = new SortField[orders.size()];

        for (int i = 0; i < orders.size(); i++) {
            final OrderDTO order = orders.get(i);
            final SortField field = new SortField(order.getName(), SortField.STRING, order.getAscending());
            fields[i] = field;
        }

        return new Sort(fields);
    }

    private final Function<PageFilter<InterviewFilterDTO>, Query> filterInterviewMapper = new Function<PageFilter<InterviewFilterDTO>, Query>() {
        public Query apply(PageFilter<InterviewFilterDTO> input) {
            final Map<String, Set<String>> classifications = input.getFilter().getClassification();
            final boolean notClass = input.getFilter().isInverse();

            final BooleanQuery classificationQuery = classification(classifications, notClass);

            final BooleanQuery conjuntion = new BooleanQuery();
            final BooleanQuery disjuntion = new BooleanQuery();

            final StringFilterDTO title = input.getFilter().getTitle();
            if (title != null) {
                if (title.isConjunction()) {
                    conjuntion.add(parsedClause(title, InterviewSchema.TITLE));
                } else {
                    disjuntion.add(parsedClause(title, InterviewSchema.TITLE));
                }
            }
            final StringFilterDTO description = input.getFilter().getDescription();
            if (description != null) {
                if (description.isConjunction()) {
                    conjuntion.add(parsedClause(description, InterviewSchema.DESCRIPTION));
                } else {
                    disjuntion.add(parsedClause(description, InterviewSchema.DESCRIPTION));
                }
            }
            final StringFilterDTO interviewee = input.getFilter().getInterviewee();
            if (interviewee != null) {
                if (interviewee.isConjunction()) {
                    conjuntion.add(parsedClause(interviewee, InterviewSchema.INTERVIEWEE));
                } else {
                    disjuntion.add(parsedClause(interviewee, InterviewSchema.INTERVIEWEE));
                }
            }
            final StringFilterDTO author = input.getFilter().getAuthor();
            if (author != null) {
                if (author.isConjunction()) {
                    conjuntion.add(parsedClause(author, InterviewSchema.AUTHOR));
                } else {
                    disjuntion.add(parsedClause(author, InterviewSchema.AUTHOR));
                }
            }

            final Integer active = input.getFilter().isActive();
            if (active != null) {
                if (active.intValue() < 0) {
                    conjuntion.add(
                            new TermRangeQuery(InterviewSchema.RELEASE, InterviewSchema.dateToString(new Date()),
                                    InterviewSchema.dateToString(InterviewSchema.getMaxDate()), false, true),
                            Occur.MUST);
                } else if (active.intValue() == 0) {
                    conjuntion.add(new TermRangeQuery(InterviewSchema.RELEASE,
                            InterviewSchema.dateToString(InterviewSchema.getMinDate()),
                            InterviewSchema.dateToString(new Date()), true, true), Occur.MUST);
                    conjuntion.add(
                            new TermRangeQuery(InterviewSchema.EXPIRATION, InterviewSchema.dateToString(new Date()),
                                    InterviewSchema.dateToString(InterviewSchema.getMaxDate()), true, true),
                            Occur.MUST);
                } else {
                    conjuntion.add(new TermRangeQuery(InterviewSchema.EXPIRATION,
                            InterviewSchema.dateToString(InterviewSchema.getMinDate()),
                            InterviewSchema.dateToString(new Date()), true, false), Occur.MUST);
                }

            }

            final Map<String, StringFilterDTO> properties = input.getFilter().getProperties();
            if (properties != null && !properties.isEmpty()) {
                for (String key : properties.keySet()) {
                    final StringFilterDTO sf = properties.get(key);
                    if (sf != null) {
                        if (sf.isConjunction()) {
                            conjuntion.add(parsedClause(sf, InterviewSchema.property(key)));
                        } else {
                            disjuntion.add(parsedClause(sf, InterviewSchema.property(key)));
                        }
                    }
                }
            }

            final BooleanQuery query = (classificationQuery != null && classificationQuery.clauses() != null
                    && !classificationQuery.clauses().isEmpty()) ? classificationQuery : new BooleanQuery();
            if (conjuntion.clauses() != null && !conjuntion.clauses().isEmpty()) {
                query.add(conjuntion, Occur.MUST);
            }
            if (disjuntion.clauses() != null && !disjuntion.clauses().isEmpty()) {
                query.add(disjuntion, Occur.MUST);
            }

            if (query.clauses() == null || query.clauses().isEmpty()) {
                return new MatchAllDocsQuery();
            }

            return query;
        }

        private BooleanQuery classification(Map<String, Set<String>> classifications, boolean notClass) {
            if (classifications == null || classifications.isEmpty()) {
                return null;
            }
            final BooleanQuery query = new BooleanQuery();

            for (String set : classifications.keySet()) {
                Set<String> classes = classifications.get(set);
                for (String c : classes) {
                    final Term t = new Term(InterviewSchema.CLASS, set + ":" + c);
                    final TermQuery q = new TermQuery(t);
                    query.add(new BooleanClause(q,
                            notClass ? BooleanClause.Occur.MUST_NOT : BooleanClause.Occur.SHOULD));
                }
            }

            final BooleanQuery queryFinal = new BooleanQuery();
            queryFinal.add(query, BooleanClause.Occur.MUST);

            return queryFinal;
        }

        private BooleanClause parsedClause(StringFilterDTO str, String field) {
            final Query q = parsedQuery(str, field);

            return new BooleanClause(q,
                    str.isConjunction() ? BooleanClause.Occur.MUST : BooleanClause.Occur.SHOULD);
        }

        private Query parsedQuery(StringFilterDTO str, String field) {
            final Query q;
            final QueryParser parser;
            if (StringMatchMode.EXACT.equals(str.getMatchMode())) {
                parser = new QueryParser(Factory.get().version(), field, analyzer);
            } else if (StringMatchMode.PREFIX.equals(str.getMatchMode())) {
                parser = new QueryParser(Factory.get().version(), field, analyzer) {
                    protected Query newTermQuery(Term term) {
                        return new WildcardQuery(new Term(term.field(), term.text() + "*"));
                    };
                };
            } else if (StringMatchMode.SUFFIX.equals(str.getMatchMode())) {
                parser = new QueryParser(Factory.get().version(), field, analyzer) {
                    protected Query newTermQuery(Term term) {
                        return new WildcardQuery(new Term(term.field(), "*" + term.text()));
                    };
                };
            } else { // StringMatchMode.IN
                parser = new QueryParser(Factory.get().version(), field, analyzer) {
                    protected Query newTermQuery(Term term) {
                        return new WildcardQuery(new Term(term.field(), "*" + term.text() + "*"));
                    };
                };
            }

            try {
                q = parser.parse(str.getValue());
            } catch (ParseException e) {
                return query(str, field);
            }

            return q;

        }

        private Query query(StringFilterDTO str, String field) {
            final Query q;
            if (StringMatchMode.EXACT.equals(str.getMatchMode())) {
                final Term t = new Term(field, str.getValue());
                q = new TermQuery(t);
            } else if (StringMatchMode.PREFIX.equals(str.getMatchMode())) {
                final Term t = new Term(field, str.getValue() + "*");
                q = new WildcardQuery(t);
            } else if (StringMatchMode.SUFFIX.equals(str.getMatchMode())) {
                final Term t = new Term(field, "*" + str.getValue());
                q = new WildcardQuery(t);
            } else { // StringMatchMode.IN
                final Term t = new Term(field, "*" + str.getValue() + "*");
                q = new WildcardQuery(t);
            }
            return q;
        }
    };

    private static final Function<Page<InterviewSelDTO>, PageDTO<InterviewSelDTO>> pageInterviewMapper = new Function<Page<InterviewSelDTO>, PageDTO<InterviewSelDTO>>() {
        public PageDTO<InterviewSelDTO> apply(Page<InterviewSelDTO> input) {
            final PageDTO<InterviewSelDTO> page = new PageDTO<InterviewSelDTO>();
            page.setElements(
                    input.getItems() == null || input.getItems().isEmpty() ? Lists.<InterviewSelDTO>newArrayList()
                            : input.getItems());
            page.setFirst(input.getFirstResult());
            page.setSize(input.size());
            page.setTotal(input.getTotalHits());

            return page;
        }
    };

    public void setStore(Store<Long> store) {
        this.store = store;
    }

    public void setAnalyzer(Analyzer analyzer) {
        this.analyzer = analyzer;
    }

    public void setMaxClauseCount(int maxClauseCount) {
        this.maxClauseCount = maxClauseCount;
    }
}