001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.search;
016    
017    import com.liferay.portal.kernel.search.facet.Facet;
018    import com.liferay.portal.kernel.search.filter.BooleanFilter;
019    import com.liferay.portal.kernel.search.filter.Filter;
020    import com.liferay.portal.kernel.search.generic.BooleanQueryImpl;
021    import com.liferay.portal.kernel.search.generic.MatchAllQuery;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.SetUtil;
024    import com.liferay.portal.kernel.util.UnicodeProperties;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portlet.expando.model.ExpandoBridge;
027    import com.liferay.portlet.expando.model.ExpandoColumnConstants;
028    import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
029    
030    import java.util.Map;
031    import java.util.Set;
032    
033    /**
034     * @author Raymond Aug??
035     */
036    public class FacetedSearcher extends BaseSearcher {
037    
038            public static Indexer<?> getInstance() {
039                    return new FacetedSearcher();
040            }
041    
042            protected void addSearchExpandoKeywords(
043                            BooleanQuery searchQuery, SearchContext searchContext,
044                            String keywords, String className)
045                    throws Exception {
046    
047                    ExpandoBridge expandoBridge = ExpandoBridgeFactoryUtil.getExpandoBridge(
048                            searchContext.getCompanyId(), className);
049    
050                    Set<String> attributeNames = SetUtil.fromEnumeration(
051                            expandoBridge.getAttributeNames());
052    
053                    for (String attributeName : attributeNames) {
054                            UnicodeProperties properties = expandoBridge.getAttributeProperties(
055                                    attributeName);
056    
057                            int indexType = GetterUtil.getInteger(
058                                    properties.getProperty(ExpandoColumnConstants.INDEX_TYPE));
059    
060                            if (indexType != ExpandoColumnConstants.INDEX_TYPE_NONE) {
061                                    String fieldName = getExpandoFieldName(
062                                            searchContext, expandoBridge, attributeName);
063    
064                                    if (searchContext.isAndSearch()) {
065                                            searchQuery.addRequiredTerm(fieldName, keywords);
066                                    }
067                                    else {
068                                            searchQuery.addTerm(fieldName, keywords);
069                                    }
070                            }
071                    }
072            }
073    
074            @Override
075            protected BooleanQuery createFullQuery(
076                            BooleanFilter fullQueryBooleanFilter, SearchContext searchContext)
077                    throws Exception {
078    
079                    BooleanQuery searchQuery = new BooleanQueryImpl();
080    
081                    String keywords = searchContext.getKeywords();
082    
083                    if (Validator.isNotNull(keywords)) {
084                            addSearchLocalizedTerm(
085                                    searchQuery, searchContext, Field.ASSET_CATEGORY_TITLES, false);
086    
087                            searchQuery.addExactTerm(Field.ASSET_TAG_NAMES, keywords);
088    
089                            int groupId = GetterUtil.getInteger(
090                                    searchContext.getAttribute(Field.GROUP_ID));
091    
092                            if (groupId == 0) {
093                                    fullQueryBooleanFilter.addTerm(
094                                            Field.STAGING_GROUP, "true", BooleanClauseOccur.MUST_NOT);
095                            }
096    
097                            searchQuery.addTerms(Field.KEYWORDS, keywords);
098                    }
099    
100                    for (String entryClassName : searchContext.getEntryClassNames()) {
101                            Indexer<?> indexer = IndexerRegistryUtil.getIndexer(entryClassName);
102    
103                            if (indexer == null) {
104                                    continue;
105                            }
106    
107                            String searchEngineId = searchContext.getSearchEngineId();
108    
109                            if (!searchEngineId.equals(indexer.getSearchEngineId())) {
110                                    continue;
111                            }
112    
113                            if (Validator.isNotNull(keywords)) {
114                                    addSearchExpandoKeywords(
115                                            searchQuery, searchContext, keywords, entryClassName);
116                            }
117    
118                            indexer.postProcessSearchQuery(
119                                    searchQuery, fullQueryBooleanFilter, searchContext);
120    
121                            for (IndexerPostProcessor indexerPostProcessor :
122                                            indexer.getIndexerPostProcessors()) {
123    
124                                    indexerPostProcessor.postProcessSearchQuery(
125                                            searchQuery, fullQueryBooleanFilter, searchContext);
126                            }
127    
128                            doPostProcessSearchQuery(indexer, searchQuery, searchContext);
129                    }
130    
131                    Map<String, Facet> facets = searchContext.getFacets();
132    
133                    BooleanFilter facetBooleanFilter = new BooleanFilter();
134    
135                    for (Facet facet : facets.values()) {
136                            BooleanClause<Filter> facetClause =
137                                    facet.getFacetFilterBooleanClause();
138    
139                            if (facetClause != null) {
140                                    facetBooleanFilter.add(
141                                            facetClause.getClause(),
142                                            facetClause.getBooleanClauseOccur());
143                            }
144                    }
145    
146                    addFacetClause(searchContext, facetBooleanFilter, facets.values());
147    
148                    if (facetBooleanFilter.hasClauses()) {
149                            fullQueryBooleanFilter.add(
150                                    facetBooleanFilter, BooleanClauseOccur.MUST);
151                    }
152    
153                    BooleanQuery fullQuery = new BooleanQueryImpl();
154    
155                    if (fullQueryBooleanFilter.hasClauses()) {
156                            fullQuery.setPreBooleanFilter(fullQueryBooleanFilter);
157                    }
158    
159                    if (searchQuery.hasClauses()) {
160                            fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
161                    }
162    
163                    BooleanClause<Query>[] booleanClauses =
164                            searchContext.getBooleanClauses();
165    
166                    if (booleanClauses != null) {
167                            for (BooleanClause<Query> booleanClause : booleanClauses) {
168                                    fullQuery.add(
169                                            booleanClause.getClause(),
170                                            booleanClause.getBooleanClauseOccur());
171                            }
172                    }
173    
174                    for (String entryClassName : searchContext.getEntryClassNames()) {
175                            Indexer<?> indexer = IndexerRegistryUtil.getIndexer(entryClassName);
176    
177                            if (indexer == null) {
178                                    continue;
179                            }
180    
181                            String searchEngineId = searchContext.getSearchEngineId();
182    
183                            if (!searchEngineId.equals(indexer.getSearchEngineId())) {
184                                    continue;
185                            }
186    
187                            for (IndexerPostProcessor indexerPostProcessor :
188                                            indexer.getIndexerPostProcessors()) {
189    
190                                    indexerPostProcessor.postProcessFullQuery(
191                                            fullQuery, searchContext);
192                            }
193                    }
194    
195                    return fullQuery;
196            }
197    
198            @Override
199            protected Hits doSearch(SearchContext searchContext)
200                    throws SearchException {
201    
202                    try {
203                            searchContext.setSearchEngineId(getSearchEngineId());
204    
205                            BooleanFilter queryBooleanFilter = new BooleanFilter();
206    
207                            queryBooleanFilter.addRequiredTerm(
208                                    Field.COMPANY_ID, searchContext.getCompanyId());
209    
210                            Query fullQuery = createFullQuery(
211                                    queryBooleanFilter, searchContext);
212    
213                            if (!fullQuery.hasChildren()) {
214                                    BooleanFilter preBooleanFilter =
215                                            fullQuery.getPreBooleanFilter();
216    
217                                    fullQuery = new MatchAllQuery();
218    
219                                    fullQuery.setPreBooleanFilter(preBooleanFilter);
220                            }
221    
222                            QueryConfig queryConfig = searchContext.getQueryConfig();
223    
224                            fullQuery.setQueryConfig(queryConfig);
225    
226                            return SearchEngineUtil.search(searchContext, fullQuery);
227                    }
228                    catch (Exception e) {
229                            throw new SearchException(e);
230                    }
231            }
232    
233            @Override
234            protected boolean isUseSearchResultPermissionFilter(
235                    SearchContext searchContext) {
236    
237                    if (searchContext.getEntryClassNames() == null) {
238                            return super.isFilterSearch();
239                    }
240    
241                    for (String entryClassName : searchContext.getEntryClassNames()) {
242                            Indexer<?> indexer = IndexerRegistryUtil.getIndexer(entryClassName);
243    
244                            if (indexer == null) {
245                                    continue;
246                            }
247    
248                            if (indexer.isFilterSearch()) {
249                                    return true;
250                            }
251                    }
252    
253                    return super.isFilterSearch();
254            }
255    
256    }