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.facet;
016    
017    import com.liferay.portal.kernel.json.JSONArray;
018    import com.liferay.portal.kernel.json.JSONFactoryUtil;
019    import com.liferay.portal.kernel.json.JSONObject;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.search.BooleanClause;
023    import com.liferay.portal.kernel.search.BooleanClauseFactoryUtil;
024    import com.liferay.portal.kernel.search.BooleanClauseOccur;
025    import com.liferay.portal.kernel.search.BooleanQuery;
026    import com.liferay.portal.kernel.search.Field;
027    import com.liferay.portal.kernel.search.Indexer;
028    import com.liferay.portal.kernel.search.IndexerPostProcessor;
029    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
030    import com.liferay.portal.kernel.search.SearchContext;
031    import com.liferay.portal.kernel.search.SearchEngineHelperUtil;
032    import com.liferay.portal.kernel.search.facet.config.FacetConfiguration;
033    import com.liferay.portal.kernel.search.filter.BooleanFilter;
034    import com.liferay.portal.kernel.search.filter.Filter;
035    import com.liferay.portal.kernel.search.filter.QueryFilter;
036    import com.liferay.portal.kernel.search.generic.BooleanQueryImpl;
037    import com.liferay.portal.kernel.util.ArrayUtil;
038    import com.liferay.portal.kernel.util.GetterUtil;
039    import com.liferay.portal.kernel.util.StringUtil;
040    
041    /**
042     * @author Raymond Aug??
043     */
044    public class AssetEntriesFacet extends MultiValueFacet {
045    
046            public AssetEntriesFacet(SearchContext searchContext) {
047                    super(searchContext);
048    
049                    setFieldName(Field.ENTRY_CLASS_NAME);
050    
051                    initFacetClause();
052            }
053    
054            @Override
055            public void setFacetConfiguration(FacetConfiguration facetConfiguration) {
056                    super.setFacetConfiguration(facetConfiguration);
057    
058                    initFacetClause();
059            }
060    
061            @Override
062            protected BooleanClause<Filter> doGetFacetFilterBooleanClause() {
063                    SearchContext searchContext = getSearchContext();
064    
065                    String[] entryClassNames = searchContext.getEntryClassNames();
066    
067                    BooleanFilter facetFilter = new BooleanFilter();
068    
069                    for (String entryClassName : entryClassNames) {
070                            Indexer<?> indexer = IndexerRegistryUtil.getIndexer(entryClassName);
071    
072                            if (indexer == null) {
073                                    continue;
074                            }
075    
076                            String searchEngineId = searchContext.getSearchEngineId();
077    
078                            if (!searchEngineId.equals(indexer.getSearchEngineId())) {
079                                    continue;
080                            }
081    
082                            try {
083                                    BooleanFilter indexerBooleanFilter =
084                                            indexer.getFacetBooleanFilter(
085                                                    entryClassName, searchContext);
086    
087                                    if ((indexerBooleanFilter == null) ||
088                                            !indexerBooleanFilter.hasClauses()) {
089    
090                                            continue;
091                                    }
092    
093                                    BooleanFilter entityBooleanFilter = new BooleanFilter();
094    
095                                    entityBooleanFilter.add(
096                                            indexerBooleanFilter, BooleanClauseOccur.MUST);
097    
098                                    indexer.postProcessContextBooleanFilter(
099                                            entityBooleanFilter, searchContext);
100    
101                                    for (IndexerPostProcessor indexerPostProcessor :
102                                                    indexer.getIndexerPostProcessors()) {
103    
104                                            indexerPostProcessor.postProcessContextBooleanFilter(
105                                                    entityBooleanFilter, searchContext);
106                                    }
107    
108                                    postProcessContextQuery(
109                                            entityBooleanFilter, searchContext, indexer);
110    
111                                    if (indexer.isStagingAware()) {
112                                            if (!searchContext.isIncludeLiveGroups() &&
113                                                    searchContext.isIncludeStagingGroups()) {
114    
115                                                    entityBooleanFilter.addRequiredTerm(
116                                                            Field.STAGING_GROUP, true);
117                                            }
118                                            else if (searchContext.isIncludeLiveGroups() &&
119                                                             !searchContext.isIncludeStagingGroups()) {
120    
121                                                    entityBooleanFilter.addRequiredTerm(
122                                                            Field.STAGING_GROUP, false);
123                                            }
124                                    }
125    
126                                    if (entityBooleanFilter.hasClauses()) {
127                                            facetFilter.add(
128                                                    entityBooleanFilter, BooleanClauseOccur.SHOULD);
129                                    }
130                            }
131                            catch (Exception e) {
132                                    _log.error(e, e);
133                            }
134                    }
135    
136                    if (!facetFilter.hasClauses()) {
137                            return null;
138                    }
139    
140                    return BooleanClauseFactoryUtil.createFilter(
141                            searchContext, facetFilter, BooleanClauseOccur.MUST);
142            }
143    
144            protected void initFacetClause() {
145                    SearchContext searchContext = getSearchContext();
146    
147                    FacetConfiguration facetConfiguration = getFacetConfiguration();
148    
149                    JSONObject dataJSONObject = facetConfiguration.getData();
150    
151                    String[] entryClassNames = null;
152    
153                    if (dataJSONObject.has("values")) {
154                            JSONArray valuesJSONArray = dataJSONObject.getJSONArray("values");
155    
156                            entryClassNames = new String[valuesJSONArray.length()];
157    
158                            for (int i = 0; i < valuesJSONArray.length(); i++) {
159                                    entryClassNames[i] = valuesJSONArray.getString(i);
160                            }
161                    }
162    
163                    if (ArrayUtil.isEmpty(entryClassNames)) {
164                            entryClassNames = searchContext.getEntryClassNames();
165                    }
166    
167                    if (!isStatic()) {
168                            String[] entryClassNameParam = StringUtil.split(
169                                    GetterUtil.getString(
170                                            searchContext.getAttribute(getFieldName())));
171    
172                            if (ArrayUtil.isNotEmpty(entryClassNameParam)) {
173                                    entryClassNames = entryClassNameParam;
174                            }
175                    }
176    
177                    if (ArrayUtil.isEmpty(entryClassNames)) {
178                            entryClassNames = SearchEngineHelperUtil.getEntryClassNames();
179    
180                            if (!dataJSONObject.has("values")) {
181                                    JSONArray entriesJSONArray = JSONFactoryUtil.createJSONArray();
182    
183                                    for (String entryClassName : entryClassNames) {
184                                            entriesJSONArray.put(entryClassName);
185                                    }
186    
187                                    dataJSONObject.put("values", entriesJSONArray);
188                            }
189                    }
190    
191                    searchContext.setEntryClassNames(entryClassNames);
192            }
193    
194            /**
195             * @deprecated As of 7.0.0, added strictly to support backwards
196             *             compatibility of {@link
197             *             Indexer#postProcessContextQuery(BooleanQuery, SearchContext)}
198             */
199            @Deprecated
200            protected void postProcessContextQuery(
201                            BooleanFilter entityFilter, SearchContext searchContext,
202                            Indexer<?> indexer)
203                    throws Exception {
204    
205                    BooleanQuery entityBooleanQuery = new BooleanQueryImpl();
206    
207                    indexer.postProcessContextQuery(entityBooleanQuery, searchContext);
208    
209                    for (IndexerPostProcessor indexerPostProcessor :
210                                    indexer.getIndexerPostProcessors()) {
211    
212                            indexerPostProcessor.postProcessContextQuery(
213                                    entityBooleanQuery, searchContext);
214                    }
215    
216                    if (entityBooleanQuery.hasClauses()) {
217                            QueryFilter queryFilter = new QueryFilter(entityBooleanQuery);
218    
219                            entityFilter.add(queryFilter, BooleanClauseOccur.MUST);
220                    }
221            }
222    
223            private static final Log _log = LogFactoryUtil.getLog(
224                    AssetEntriesFacet.class);
225    
226    }