001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.util.GetterUtil;
019    import com.liferay.portal.kernel.util.SetUtil;
020    import com.liferay.portal.kernel.util.UnicodeProperties;
021    import com.liferay.portal.kernel.util.Validator;
022    import com.liferay.portal.model.Group;
023    import com.liferay.portal.service.GroupLocalServiceUtil;
024    import com.liferay.portlet.expando.model.ExpandoBridge;
025    import com.liferay.portlet.expando.model.ExpandoColumnConstants;
026    import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
027    import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
028    
029    import java.util.List;
030    import java.util.Locale;
031    import java.util.Map;
032    import java.util.Set;
033    
034    import javax.portlet.PortletURL;
035    
036    /**
037     * @author Raymond Aug??
038     */
039    public class FacetedSearcher extends BaseIndexer {
040    
041            public static Indexer getInstance() {
042                    return new FacetedSearcher();
043            }
044    
045            @Override
046            public String[] getClassNames() {
047                    return null;
048            }
049    
050            @Override
051            public IndexerPostProcessor[] getIndexerPostProcessors() {
052                    throw new UnsupportedOperationException();
053            }
054    
055            @Override
056            public String getPortletId() {
057                    return null;
058            }
059    
060            @Override
061            public void registerIndexerPostProcessor(
062                    IndexerPostProcessor indexerPostProcessor) {
063    
064                    throw new UnsupportedOperationException();
065            }
066    
067            @Override
068            public void unregisterIndexerPostProcessor(
069                    IndexerPostProcessor indexerPostProcessor) {
070    
071                    throw new UnsupportedOperationException();
072            }
073    
074            protected void addSearchExpandoKeywords(
075                            BooleanQuery searchQuery, SearchContext searchContext,
076                            String keywords, String className)
077                    throws Exception {
078    
079                    ExpandoBridge expandoBridge = ExpandoBridgeFactoryUtil.getExpandoBridge(
080                            searchContext.getCompanyId(), className);
081    
082                    Set<String> attributeNames = SetUtil.fromEnumeration(
083                            expandoBridge.getAttributeNames());
084    
085                    for (String attributeName : attributeNames) {
086                            UnicodeProperties properties = expandoBridge.getAttributeProperties(
087                                    attributeName);
088    
089                            int indexType = GetterUtil.getInteger(
090                                    properties.getProperty(ExpandoColumnConstants.INDEX_TYPE));
091    
092                            if (indexType != ExpandoColumnConstants.INDEX_TYPE_NONE) {
093                                    String fieldName = ExpandoBridgeIndexerUtil.encodeFieldName(
094                                            attributeName);
095    
096                                    if (searchContext.isAndSearch()) {
097                                            searchQuery.addRequiredTerm(fieldName, keywords);
098                                    }
099                                    else {
100                                            searchQuery.addTerm(fieldName, keywords);
101                                    }
102                            }
103                    }
104            }
105    
106            @Override
107            protected BooleanQuery createFullQuery(
108                            BooleanQuery contextQuery, SearchContext searchContext)
109                    throws Exception {
110    
111                    BooleanQuery searchQuery = BooleanQueryFactoryUtil.create(
112                            searchContext);
113    
114                    String keywords = searchContext.getKeywords();
115    
116                    if (Validator.isNotNull(keywords)) {
117                            addSearchLocalizedTerm(
118                                    searchQuery, searchContext, Field.ASSET_CATEGORY_TITLES, false);
119    
120                            searchQuery.addExactTerm(Field.ASSET_TAG_NAMES, keywords);
121                            searchQuery.addTerms(Field.KEYWORDS, keywords);
122    
123                            int groupId = GetterUtil.getInteger(
124                                    searchContext.getAttribute(Field.GROUP_ID));
125    
126                            if (groupId == 0) {
127                                    searchQuery.addTerm(
128                                            Field.STAGING_GROUP, "true", false,
129                                            BooleanClauseOccur.MUST_NOT);
130                            }
131                    }
132    
133                    List<Group> inactiveGroups = GroupLocalServiceUtil.getActiveGroups(
134                            searchContext.getCompanyId(), false);
135    
136                    for (Group inactiveGroup : inactiveGroups) {
137                            searchQuery.addTerm(
138                                    Field.GROUP_ID, String.valueOf(inactiveGroup.getGroupId()),
139                                    false, BooleanClauseOccur.MUST_NOT);
140                    }
141    
142                    for (String entryClassName : searchContext.getEntryClassNames()) {
143                            Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
144    
145                            if (indexer == null) {
146                                    continue;
147                            }
148    
149                            String searchEngineId = searchContext.getSearchEngineId();
150    
151                            if (!searchEngineId.equals(indexer.getSearchEngineId())) {
152                                    continue;
153                            }
154    
155                            if (Validator.isNotNull(keywords)) {
156                                    addSearchExpandoKeywords(
157                                            searchQuery, searchContext, keywords, entryClassName);
158                            }
159    
160                            indexer.postProcessSearchQuery(searchQuery, searchContext);
161    
162                            for (IndexerPostProcessor indexerPostProcessor :
163                                            indexer.getIndexerPostProcessors()) {
164    
165                                    indexerPostProcessor.postProcessSearchQuery(
166                                            searchQuery, searchContext);
167                            }
168                    }
169    
170                    Map<String, Facet> facets = searchContext.getFacets();
171    
172                    for (Facet facet : facets.values()) {
173                            BooleanClause facetClause = facet.getFacetClause();
174    
175                            if (facetClause != null) {
176                                    contextQuery.add(
177                                            facetClause.getQuery(),
178                                            facetClause.getBooleanClauseOccur());
179                            }
180                    }
181    
182                    BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
183    
184                    fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
185    
186                    if (searchQuery.hasClauses()) {
187                            fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
188                    }
189    
190                    BooleanClause[] booleanClauses = searchContext.getBooleanClauses();
191    
192                    if (booleanClauses != null) {
193                            for (BooleanClause booleanClause : booleanClauses) {
194                                    fullQuery.add(
195                                            booleanClause.getQuery(),
196                                            booleanClause.getBooleanClauseOccur());
197                            }
198                    }
199    
200                    for (String entryClassName : searchContext.getEntryClassNames()) {
201                            Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
202    
203                            if (indexer == null) {
204                                    continue;
205                            }
206    
207                            String searchEngineId = searchContext.getSearchEngineId();
208    
209                            if (!searchEngineId.equals(indexer.getSearchEngineId())) {
210                                    continue;
211                            }
212    
213                            for (IndexerPostProcessor indexerPostProcessor :
214                                            indexer.getIndexerPostProcessors()) {
215    
216                                    indexerPostProcessor.postProcessFullQuery(
217                                            fullQuery, searchContext);
218                            }
219                    }
220    
221                    return fullQuery;
222            }
223    
224            @Override
225            protected void doDelete(Object obj) throws Exception {
226                    throw new UnsupportedOperationException();
227            }
228    
229            @Override
230            protected Document doGetDocument(Object obj) throws Exception {
231                    throw new UnsupportedOperationException();
232            }
233    
234            @Override
235            protected Summary doGetSummary(
236                            Document document, Locale locale, String snippet,
237                            PortletURL portletURL)
238                    throws Exception {
239    
240                    throw new UnsupportedOperationException();
241            }
242    
243            @Override
244            protected void doReindex(Object obj) throws Exception {
245                    throw new UnsupportedOperationException();
246            }
247    
248            @Override
249            protected void doReindex(String className, long classPK) throws Exception {
250                    throw new UnsupportedOperationException();
251            }
252    
253            @Override
254            protected void doReindex(String[] ids) throws Exception {
255                    throw new UnsupportedOperationException();
256            }
257    
258            @Override
259            protected Hits doSearch(SearchContext searchContext)
260                    throws SearchException {
261    
262                    try {
263                            searchContext.setSearchEngineId(getSearchEngineId());
264    
265                            BooleanQuery contextQuery = BooleanQueryFactoryUtil.create(
266                                    searchContext);
267    
268                            contextQuery.addRequiredTerm(
269                                    Field.COMPANY_ID, searchContext.getCompanyId());
270    
271                            BooleanQuery fullQuery = createFullQuery(
272                                    contextQuery, searchContext);
273    
274                            QueryConfig queryConfig = searchContext.getQueryConfig();
275    
276                            fullQuery.setQueryConfig(queryConfig);
277    
278                            return SearchEngineUtil.search(searchContext, fullQuery);
279                    }
280                    catch (Exception e) {
281                            throw new SearchException(e);
282                    }
283            }
284    
285            @Override
286            protected String getPortletId(SearchContext searchContext) {
287                    return null;
288            }
289    
290            /**
291             * @deprecated As of 6.2.0, replaced by {@link
292             *             #isUseSearchResultPermissionFilter(SearchContext)}
293             */
294            protected boolean isFilterSearch(SearchContext searchContext) {
295                    return isUseSearchResultPermissionFilter(searchContext);
296            }
297    
298            @Override
299            protected boolean isUseSearchResultPermissionFilter(
300                    SearchContext searchContext) {
301    
302                    if (searchContext.getEntryClassNames() == null) {
303                            return super.isFilterSearch();
304                    }
305    
306                    for (String entryClassName : searchContext.getEntryClassNames()) {
307                            Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
308    
309                            if (indexer == null) {
310                                    continue;
311                            }
312    
313                            if (indexer.isFilterSearch()) {
314                                    return true;
315                            }
316                    }
317    
318                    return super.isFilterSearch();
319            }
320    
321    }