Java tutorial
/* * Copyright (c) 2002-2013, Mairie de Paris * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright notice * and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice * and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * License 1.0 */ package fr.paris.lutece.portal.service.search; import fr.paris.lutece.portal.business.page.Page; import fr.paris.lutece.portal.service.security.LuteceUser; import fr.paris.lutece.portal.service.security.SecurityService; import fr.paris.lutece.portal.service.util.AppLogService; import fr.paris.lutece.util.date.DateUtil; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.lucene.document.DateTools; import org.apache.lucene.document.DateTools.Resolution; import org.apache.lucene.document.Document; import org.apache.lucene.index.Term; import org.apache.lucene.misc.ChainedFilter; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.CachingWrapperFilter; import org.apache.lucene.search.Filter; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.QueryWrapperFilter; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.Searcher; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermRangeQuery; import org.apache.lucene.search.TopDocs; /** * LuceneSearchEngine */ public class LuceneSearchEngine implements SearchEngine { public static final int MAX_RESPONSES = 1000000; private static final String PARAMETER_TYPE_FILTER = "type_filter"; private static final String PARAMETER_DATE_AFTER = "date_after"; private static final String PARAMETER_DATE_BEFORE = "date_before"; private static final String PARAMETER_TAG_FILTER = "tag_filter"; private static final String PARAMETER_DEFAULT_OPERATOR = "default_operator"; private static final String PARAMETER_OPERATOR_AND = "AND"; /** * Return search results * * @param strQuery The search query * @param request The HTTP request * @return Results as a collection of SearchResult */ public List<SearchResult> getSearchResults(String strQuery, HttpServletRequest request) { ArrayList<SearchItem> listResults = new ArrayList<SearchItem>(); ArrayList<Filter> listFilter = new ArrayList<Filter>(); Searcher searcher = null; boolean bFilterResult = false; LuteceUser user = null; String[] typeFilter = request.getParameterValues(PARAMETER_TYPE_FILTER); String strDateAfter = request.getParameter(PARAMETER_DATE_AFTER); String strDateBefore = request.getParameter(PARAMETER_DATE_BEFORE); boolean bDateAfter = false; boolean bDateBefore = false; Filter allFilter = null; String strTagFilter = request.getParameter(PARAMETER_TAG_FILTER); if (SecurityService.isAuthenticationEnable()) { user = SecurityService.getInstance().getRegisteredUser(request); Filter[] filtersRole = null; if (user != null) { String[] userRoles = SecurityService.getInstance().getRolesByUser(user); if (userRoles != null) { filtersRole = new Filter[userRoles.length + 1]; for (int i = 0; i < userRoles.length; i++) { Query queryRole = new TermQuery(new Term(SearchItem.FIELD_ROLE, userRoles[i])); filtersRole[i] = new CachingWrapperFilter(new QueryWrapperFilter(queryRole)); } } else { bFilterResult = true; } } else { filtersRole = new Filter[1]; } if (!bFilterResult) { Query queryRole = new TermQuery(new Term(SearchItem.FIELD_ROLE, Page.ROLE_NONE)); filtersRole[filtersRole.length - 1] = new CachingWrapperFilter(new QueryWrapperFilter(queryRole)); listFilter.add(new ChainedFilter(filtersRole, ChainedFilter.OR)); } } if (StringUtils.isNotBlank(strDateAfter) || StringUtils.isNotBlank(strDateBefore)) { String strAfter = null; String strBefore = null; if (StringUtils.isNotBlank(strDateAfter)) { Date dateAfter = DateUtil.formatDate(strDateAfter, request.getLocale()); strAfter = DateTools.dateToString(dateAfter, Resolution.DAY); bDateAfter = true; } if (StringUtils.isNotBlank(strDateBefore)) { Date dateBefore = DateUtil.formatDate(strDateBefore, request.getLocale()); strBefore = DateTools.dateToString(dateBefore, Resolution.DAY); bDateBefore = true; } Query queryDate = new TermRangeQuery(SearchItem.FIELD_DATE, strAfter, strBefore, bDateAfter, bDateBefore); listFilter.add(new CachingWrapperFilter(new QueryWrapperFilter(queryDate))); } if ((typeFilter != null) && (typeFilter.length > 0) && !typeFilter[0].equals(SearchService.TYPE_FILTER_NONE)) { Filter[] filtersType = new Filter[typeFilter.length]; for (int i = 0; i < typeFilter.length; i++) { Query queryType = new TermQuery(new Term(SearchItem.FIELD_TYPE, typeFilter[i])); filtersType[i] = new CachingWrapperFilter(new QueryWrapperFilter(queryType)); } listFilter.add(new ChainedFilter(filtersType, ChainedFilter.OR)); } if (!listFilter.isEmpty()) { allFilter = new ChainedFilter(listFilter.toArray(new Filter[1]), ChainedFilter.AND); } try { searcher = new IndexSearcher(IndexationService.getDirectoryIndex(), true); Query query = null; if (StringUtils.isNotBlank(strTagFilter)) { BooleanQuery bQuery = new BooleanQuery(); QueryParser parser = new QueryParser(IndexationService.LUCENE_INDEX_VERSION, SearchItem.FIELD_METADATA, IndexationService.getAnalyser()); Query queryMetaData = parser.parse((strQuery != null) ? strQuery : ""); bQuery.add(queryMetaData, BooleanClause.Occur.SHOULD); parser = new QueryParser(IndexationService.LUCENE_INDEX_VERSION, SearchItem.FIELD_SUMMARY, IndexationService.getAnalyser()); Query querySummary = parser.parse((strQuery != null) ? strQuery : ""); bQuery.add(querySummary, BooleanClause.Occur.SHOULD); query = bQuery; } else { QueryParser parser = new QueryParser(IndexationService.LUCENE_INDEX_VERSION, SearchItem.FIELD_CONTENTS, IndexationService.getAnalyser()); String operator = request.getParameter(PARAMETER_DEFAULT_OPERATOR); if (StringUtils.isNotEmpty(operator) && operator.equals(PARAMETER_OPERATOR_AND)) { parser.setDefaultOperator(QueryParser.AND_OPERATOR); } query = parser.parse((strQuery != null) ? strQuery : ""); } // Get results documents TopDocs topDocs = searcher.search(query, allFilter, MAX_RESPONSES); ScoreDoc[] hits = topDocs.scoreDocs; for (int i = 0; i < hits.length; i++) { int docId = hits[i].doc; Document document = searcher.doc(docId); SearchItem si = new SearchItem(document); if ((!bFilterResult) || (si.getRole().equals(Page.ROLE_NONE)) || (SecurityService.getInstance().isUserInRole(request, si.getRole()))) { listResults.add(si); } } searcher.close(); } catch (Exception e) { AppLogService.error(e.getMessage(), e); } return convertList(listResults); } /** * Convert a list of Lucene items into a list of generic search items * @param listSource The list of Lucene items * @return A list of generic search items */ private List<SearchResult> convertList(List<SearchItem> listSource) { List<SearchResult> listDest = new ArrayList<SearchResult>(); for (SearchItem item : listSource) { SearchResult result = new SearchResult(); result.setId(item.getId()); try { result.setDate(DateTools.stringToDate(item.getDate())); } catch (ParseException e) { AppLogService .error("Bad Date Format for indexed item \"" + item.getTitle() + "\" : " + e.getMessage()); } result.setUrl(item.getUrl()); result.setTitle(item.getTitle()); result.setSummary(item.getSummary()); result.setType(item.getType()); listDest.add(result); } return listDest; } }