org.alfresco.repo.search.impl.lucene.LuceneAlfrescoLuceneQueryLanguage.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.repo.search.impl.lucene.LuceneAlfrescoLuceneQueryLanguage.java

Source

/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.repo.search.impl.lucene;

import java.io.IOException;
import java.util.Locale;

import org.alfresco.repo.dictionary.IndexTokenisationMode;
import org.alfresco.repo.search.EmptyResultSet;
import org.alfresco.repo.search.SearcherException;
import org.alfresco.repo.search.impl.lucene.analysis.DateTimeAnalyser;
import org.alfresco.repo.search.results.SortedResultSet;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.index.IndexReader.FieldOption;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser.Operator;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;

/**
 * Alfresco FTS Query language support
 * 
 * @author andyh
 */
public class LuceneAlfrescoLuceneQueryLanguage extends AbstractLuceneQueryLanguage {
    static Log s_logger = LogFactory.getLog(LuceneAlfrescoLuceneQueryLanguage.class);

    public LuceneAlfrescoLuceneQueryLanguage() {
        this.setName(SearchService.LANGUAGE_LUCENE);
    }

    public ResultSet executeQuery(SearchParameters searchParameters, ADMLuceneSearcherImpl admLuceneSearcher) {
        try {

            Operator defaultOperator;
            if (searchParameters.getDefaultOperator() == SearchParameters.AND) {
                defaultOperator = LuceneQueryParser.AND_OPERATOR;
            } else {
                defaultOperator = LuceneQueryParser.OR_OPERATOR;
            }

            ClosingIndexSearcher searcher = admLuceneSearcher.getClosingIndexSearcher();
            if (searcher == null) {
                // no index return an empty result set
                return new EmptyResultSet();
            }
            Query query = LuceneQueryParser.parse(searchParameters.getQuery(),
                    searchParameters.getDefaultFieldName(),
                    new LuceneAnalyser(admLuceneSearcher.getDictionaryService(),
                            searchParameters.getMlAnalaysisMode() == null
                                    ? admLuceneSearcher.getLuceneConfig().getDefaultMLSearchAnalysisMode()
                                    : searchParameters.getMlAnalaysisMode()),
                    admLuceneSearcher.getNamespacePrefixResolver(), admLuceneSearcher.getDictionaryService(),
                    admLuceneSearcher.getTenantService(), defaultOperator, searchParameters,
                    admLuceneSearcher.getLuceneConfig().getDefaultMLSearchAnalysisMode(),
                    searcher.getIndexReader());
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Query is " + query.toString());
            }

            Hits hits;

            boolean requiresDateTimePostSort = false;
            SortField[] fields = new SortField[searchParameters.getSortDefinitions().size()];

            if (searchParameters.getSortDefinitions().size() > 0) {
                int index = 0;
                for (SearchParameters.SortDefinition sd : searchParameters.getSortDefinitions()) {
                    switch (sd.getSortType()) {
                    case FIELD:
                        Locale sortLocale = searchParameters.getSortLocale();
                        String field = sd.getField();
                        if (field.startsWith("@")) {
                            field = admLuceneSearcher.expandAttributeFieldName(field);
                            PropertyDefinition propertyDef = admLuceneSearcher.getDictionaryService()
                                    .getProperty(QName.createQName(field.substring(1)));

                            if (propertyDef == null) {
                                if (field.endsWith(".size")) {
                                    propertyDef = admLuceneSearcher.getDictionaryService()
                                            .getProperty(QName.createQName(field.substring(1, field.length() - 5)));
                                    if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) {
                                        throw new SearcherException(
                                                "Order for .size only supported on content properties");
                                    }
                                } else if (field.endsWith(".mimetype")) {
                                    propertyDef = admLuceneSearcher.getDictionaryService()
                                            .getProperty(QName.createQName(field.substring(1, field.length() - 9)));
                                    if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) {
                                        throw new SearcherException(
                                                "Order for .mimetype only supported on content properties");
                                    }
                                } else {
                                    // nothing
                                }
                            } else {
                                if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) {
                                    throw new SearcherException(
                                            "Order on content properties is not curently supported");
                                }

                                else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)) {
                                    if (propertyDef.getIndexTokenisationMode() == IndexTokenisationMode.FALSE) {
                                        // use field as is
                                    } else {

                                        String noLocalField = field + ".no_locale";
                                        for (Object current : searcher.getIndexReader()
                                                .getFieldNames(FieldOption.INDEXED)) {
                                            String currentString = (String) current;
                                            if (currentString.equals(noLocalField)) {
                                                field = noLocalField;
                                            }
                                        }

                                        if (!field.endsWith(".no_locale")) {
                                            field = admLuceneSearcher.findSortField(searchParameters, searcher,
                                                    field, sortLocale);
                                        }
                                    }
                                }

                                else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT)) {

                                    field = admLuceneSearcher.findSortField(searchParameters, searcher, field,
                                            sortLocale);

                                } else if (propertyDef.getDataType().getName()
                                        .equals(DataTypeDefinition.DATETIME)) {
                                    DataTypeDefinition dataType = propertyDef.getDataType();
                                    String analyserClassName = propertyDef.resolveAnalyserClassName();
                                    if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName())) {
                                        switch (propertyDef.getIndexTokenisationMode()) {
                                        case TRUE:
                                            requiresDateTimePostSort = true;
                                            break;
                                        case BOTH:
                                            field = field + ".sort";
                                            break;
                                        case FALSE:
                                            // Should be able to sort on actual field OK
                                            break;
                                        }
                                    } else {
                                        requiresDateTimePostSort = true;
                                    }
                                }
                            }
                        }

                        if (LuceneUtils.fieldHasTerm(searcher.getReader(), field)) {
                            fields[index++] = new SortField(field, sortLocale, !sd.isAscending());
                        } else {
                            fields[index++] = new SortField(null, SortField.DOC, !sd.isAscending());
                        }
                        break;
                    case DOCUMENT:
                        fields[index++] = new SortField(null, SortField.DOC, !sd.isAscending());
                        break;
                    case SCORE:
                        // Score is naturally high to low -ie desc
                        fields[index++] = new SortField(null, SortField.SCORE, sd.isAscending());
                        break;
                    }

                }
            }

            hits = searcher.search(query);

            boolean postSort = false;
            ;
            if (fields.length > 0) {
                postSort = searchParameters.usePostSort(hits.length(),
                        admLuceneSearcher.getLuceneConfig().getUseInMemorySort(),
                        admLuceneSearcher.getLuceneConfig().getMaxRawResultSetSizeForInMemorySort());
                if (postSort == false) {
                    hits = searcher.search(query, new Sort(fields));
                }
            }

            ResultSet answer;
            ResultSet result = new LuceneResultSet(hits, searcher, admLuceneSearcher.getNodeService(),
                    admLuceneSearcher.getTenantService(), searchParameters, admLuceneSearcher.getLuceneConfig());
            if (postSort
                    || (admLuceneSearcher.getLuceneConfig().getPostSortDateTime() && requiresDateTimePostSort)) {
                ResultSet sorted = new SortedResultSet(result, admLuceneSearcher.getNodeService(),
                        searchParameters.getSortDefinitions(), admLuceneSearcher.getNamespacePrefixResolver(),
                        admLuceneSearcher.getDictionaryService(), searchParameters.getSortLocale());
                answer = sorted;
            } else {
                answer = result;
            }
            ResultSet rs = new PagingLuceneResultSet(answer, searchParameters, admLuceneSearcher.getNodeService());
            return rs;
        } catch (ParseException e) {
            throw new SearcherException("Failed to parse query: " + searchParameters.getQuery(), e);
        } catch (IOException e) {
            throw new SearcherException("IO exception during search", e);
        }
    }

}