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.portlet.assetpublisher.util;
016    
017    import com.liferay.portal.kernel.search.BaseSearcher;
018    import com.liferay.portal.kernel.search.BooleanClauseOccur;
019    import com.liferay.portal.kernel.search.BooleanQuery;
020    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
021    import com.liferay.portal.kernel.search.DocumentImpl;
022    import com.liferay.portal.kernel.search.Field;
023    import com.liferay.portal.kernel.search.Indexer;
024    import com.liferay.portal.kernel.search.SearchContext;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portal.security.permission.PermissionChecker;
027    import com.liferay.portal.security.permission.PermissionThreadLocal;
028    import com.liferay.portal.util.PortalUtil;
029    import com.liferay.portal.util.PropsValues;
030    import com.liferay.portlet.asset.model.AssetCategory;
031    import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
032    import com.liferay.portlet.asset.service.persistence.AssetEntryQuery;
033    import com.liferay.portlet.asset.util.AssetUtil;
034    
035    import java.util.ArrayList;
036    import java.util.List;
037    
038    /**
039     * @author Eudaldo Alonso
040     */
041    public class AssetSearcher extends BaseSearcher {
042    
043            public static Indexer getInstance() {
044                    return new AssetSearcher();
045            }
046    
047            public AssetSearcher() {
048                    setDefaultSelectedFieldNames(
049                            Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.UID);
050                    setFilterSearch(true);
051                    setPermissionAware(true);
052            }
053    
054            @Override
055            public String[] getClassNames() {
056                    long[] classNameIds = _assetEntryQuery.getClassNameIds();
057    
058                    String[] classNames = new String[classNameIds.length];
059    
060                    for (int i = 0; i < classNames.length; i++) {
061                            long classNameId = classNameIds[i];
062    
063                            classNames[i] = PortalUtil.getClassName(classNameId);
064                    }
065    
066                    return classNames;
067            }
068    
069            public void setAssetEntryQuery(AssetEntryQuery assetEntryQuery) {
070                    _assetEntryQuery = assetEntryQuery;
071            }
072    
073            protected void addImpossibleTerm(BooleanQuery contextQuery, String field)
074                    throws Exception {
075    
076                    contextQuery.addTerm(field, "-1", false, BooleanClauseOccur.MUST);
077            }
078    
079            protected void addSearchAllCategories(
080                            BooleanQuery contextQuery, SearchContext searchContext)
081                    throws Exception {
082    
083                    PermissionChecker permissionChecker =
084                            PermissionThreadLocal.getPermissionChecker();
085    
086                    long[] allCategoryIds = _assetEntryQuery.getAllCategoryIds();
087    
088                    if (allCategoryIds.length == 0) {
089                            return;
090                    }
091    
092                    long[] filteredAllCategoryIds = AssetUtil.filterCategoryIds(
093                            permissionChecker, allCategoryIds);
094    
095                    if (allCategoryIds.length != filteredAllCategoryIds.length) {
096                            addImpossibleTerm(contextQuery, Field.ASSET_CATEGORY_IDS);
097    
098                            return;
099                    }
100    
101                    BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create(
102                            searchContext);
103    
104                    for (long allCategoryId : filteredAllCategoryIds) {
105                            AssetCategory assetCategory =
106                                    AssetCategoryLocalServiceUtil.fetchAssetCategory(allCategoryId);
107    
108                            if (assetCategory == null) {
109                                    continue;
110                            }
111    
112                            List<Long> categoryIds = new ArrayList<Long>();
113    
114                            if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
115                                    categoryIds.addAll(
116                                            AssetCategoryLocalServiceUtil.getSubcategoryIds(
117                                                    allCategoryId));
118                            }
119    
120                            if (categoryIds.isEmpty()) {
121                                    categoryIds.add(allCategoryId);
122                            }
123    
124                            BooleanQuery categoryIdQuery = BooleanQueryFactoryUtil.create(
125                                    searchContext);
126    
127                            for (long categoryId : categoryIds) {
128                                    categoryIdQuery.addTerm(Field.ASSET_CATEGORY_IDS, categoryId);
129                            }
130    
131                            categoryIdsQuery.add(categoryIdQuery, BooleanClauseOccur.MUST);
132                    }
133    
134                    contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
135            }
136    
137            protected void addSearchAllTags(
138                            BooleanQuery contextQuery, SearchContext searchContext)
139                    throws Exception {
140    
141                    PermissionChecker permissionChecker =
142                            PermissionThreadLocal.getPermissionChecker();
143    
144                    long[] allTagIds = _assetEntryQuery.getAllTagIds();
145    
146                    if (allTagIds.length == 0) {
147                            return;
148                    }
149    
150                    long[] filteredAllTagIds = AssetUtil.filterTagIds(
151                            permissionChecker, allTagIds);
152    
153                    if (allTagIds.length != filteredAllTagIds.length) {
154                            addImpossibleTerm(contextQuery, Field.ASSET_TAG_IDS);
155    
156                            return;
157                    }
158    
159                    BooleanQuery tagIdsQuery = BooleanQueryFactoryUtil.create(
160                            searchContext);
161    
162                    for (long tagId : allTagIds) {
163                            tagIdsQuery.addRequiredTerm(Field.ASSET_TAG_IDS, tagId);
164                    }
165    
166                    contextQuery.add(tagIdsQuery, BooleanClauseOccur.MUST);
167            }
168    
169            protected void addSearchAnyCategories(
170                            BooleanQuery contextQuery, SearchContext searchContext)
171                    throws Exception {
172    
173                    PermissionChecker permissionChecker =
174                            PermissionThreadLocal.getPermissionChecker();
175    
176                    long[] anyCategoryIds = _assetEntryQuery.getAnyCategoryIds();
177    
178                    if (anyCategoryIds.length == 0) {
179                            return;
180                    }
181    
182                    long[] filteredAnyCategoryIds = AssetUtil.filterCategoryIds(
183                            permissionChecker, anyCategoryIds);
184    
185                    if (filteredAnyCategoryIds.length == 0) {
186                            addImpossibleTerm(contextQuery, Field.ASSET_CATEGORY_IDS);
187    
188                            return;
189                    }
190    
191                    BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create(
192                            searchContext);
193    
194                    for (long anyCategoryId : filteredAnyCategoryIds) {
195                            AssetCategory assetCategory =
196                                    AssetCategoryLocalServiceUtil.fetchAssetCategory(anyCategoryId);
197    
198                            if (assetCategory == null) {
199                                    continue;
200                            }
201    
202                            List<Long> categoryIds = new ArrayList<Long>();
203    
204                            if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
205                                    categoryIds.addAll(
206                                            AssetCategoryLocalServiceUtil.getSubcategoryIds(
207                                                    anyCategoryId));
208                            }
209    
210                            if (categoryIds.isEmpty()) {
211                                    categoryIds.add(anyCategoryId);
212                            }
213    
214                            for (long categoryId : categoryIds) {
215                                    categoryIdsQuery.addTerm(Field.ASSET_CATEGORY_IDS, categoryId);
216                            }
217                    }
218    
219                    contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
220            }
221    
222            protected void addSearchAnyTags(
223                            BooleanQuery contextQuery, SearchContext searchContext)
224                    throws Exception {
225    
226                    PermissionChecker permissionChecker =
227                            PermissionThreadLocal.getPermissionChecker();
228    
229                    long[] anyTagIds = _assetEntryQuery.getAnyTagIds();
230    
231                    if (anyTagIds.length == 0) {
232                            return;
233                    }
234    
235                    long[] filteredAnyTagIds = AssetUtil.filterTagIds(
236                            permissionChecker, anyTagIds);
237    
238                    if (filteredAnyTagIds.length == 0) {
239                            addImpossibleTerm(contextQuery, Field.ASSET_TAG_IDS);
240    
241                            return;
242                    }
243    
244                    BooleanQuery tagIdsQuery = BooleanQueryFactoryUtil.create(
245                            searchContext);
246    
247                    for (long tagId : anyTagIds) {
248                            tagIdsQuery.addTerm(Field.ASSET_TAG_IDS, tagId);
249                    }
250    
251                    contextQuery.add(tagIdsQuery, BooleanClauseOccur.MUST);
252            }
253    
254            @Override
255            protected void addSearchAssetCategoryIds(
256                            BooleanQuery contextQuery, SearchContext searchContext)
257                    throws Exception {
258    
259                    addSearchAllCategories(contextQuery, searchContext);
260                    addSearchAnyCategories(contextQuery, searchContext);
261                    addSearchNotAnyCategories(contextQuery, searchContext);
262                    addSearchNotAllCategories(contextQuery, searchContext);
263            }
264    
265            @Override
266            protected void addSearchAssetTagNames(
267                            BooleanQuery contextQuery, SearchContext searchContext)
268                    throws Exception {
269    
270                    addSearchAllTags(contextQuery, searchContext);
271                    addSearchAnyTags(contextQuery, searchContext);
272                    addSearchNotAllTags(contextQuery, searchContext);
273                    addSearchNotAnyTags(contextQuery, searchContext);
274            }
275    
276            @Override
277            protected void addSearchKeywords(
278                            BooleanQuery searchQuery, SearchContext searchContext)
279                    throws Exception {
280    
281                    String keywords = searchContext.getKeywords();
282    
283                    if (Validator.isNull(keywords)) {
284                            return;
285                    }
286    
287                    super.addSearchKeywords(searchQuery, searchContext);
288    
289                    String field = DocumentImpl.getLocalizedName(
290                            searchContext.getLocale(), "localized_title");
291    
292                    searchQuery.addTerm(field, keywords, true);
293            }
294    
295            @Override
296            protected void addSearchLayout(
297                            BooleanQuery contextQuery, SearchContext searchContext)
298                    throws Exception {
299    
300                    String layoutUuid = (String)searchContext.getAttribute(
301                            Field.LAYOUT_UUID);
302    
303                    if (Validator.isNotNull(layoutUuid)) {
304                            contextQuery.addRequiredTerm(Field.LAYOUT_UUID, layoutUuid);
305                    }
306            }
307    
308            protected void addSearchNotAllCategories(
309                            BooleanQuery contextQuery, SearchContext searchContext)
310                    throws Exception {
311    
312                    long[] notAllCategoryIds = _assetEntryQuery.getNotAllCategoryIds();
313    
314                    if (notAllCategoryIds.length == 0) {
315                            return;
316                    }
317    
318                    BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create(
319                            searchContext);
320    
321                    for (long notAllCategoryId : notAllCategoryIds) {
322                            AssetCategory assetCategory =
323                                    AssetCategoryLocalServiceUtil.fetchAssetCategory(
324                                            notAllCategoryId);
325    
326                            if (assetCategory == null) {
327                                    continue;
328                            }
329    
330                            List<Long> categoryIds = new ArrayList<Long>();
331    
332                            if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
333                                    categoryIds.addAll(
334                                            AssetCategoryLocalServiceUtil.getSubcategoryIds(
335                                                    notAllCategoryId));
336                            }
337    
338                            if (categoryIds.isEmpty()) {
339                                    categoryIds.add(notAllCategoryId);
340                            }
341    
342                            BooleanQuery categoryIdQuery = BooleanQueryFactoryUtil.create(
343                                    searchContext);
344    
345                            for (long categoryId : categoryIds) {
346                                    categoryIdQuery.addTerm(Field.ASSET_CATEGORY_IDS, categoryId);
347                            }
348    
349                            categoryIdsQuery.add(categoryIdQuery, BooleanClauseOccur.MUST);
350                    }
351    
352                    contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST_NOT);
353            }
354    
355            protected void addSearchNotAllTags(
356                            BooleanQuery contextQuery, SearchContext searchContext)
357                    throws Exception {
358    
359                    long[] notAllTagIds = _assetEntryQuery.getNotAllTagIds();
360    
361                    if (notAllTagIds.length == 0) {
362                            return;
363                    }
364    
365                    BooleanQuery tagIdsQuery = BooleanQueryFactoryUtil.create(
366                            searchContext);
367    
368                    for (long tagId : notAllTagIds) {
369                            tagIdsQuery.addRequiredTerm(Field.ASSET_TAG_IDS, tagId);
370                    }
371    
372                    contextQuery.add(tagIdsQuery, BooleanClauseOccur.MUST_NOT);
373            }
374    
375            protected void addSearchNotAnyCategories(
376                            BooleanQuery contextQuery, SearchContext searchContext)
377                    throws Exception {
378    
379                    long[] notAnyCategoryIds = _assetEntryQuery.getNotAnyCategoryIds();
380    
381                    if (notAnyCategoryIds.length == 0) {
382                            return;
383                    }
384    
385                    BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create(
386                            searchContext);
387    
388                    for (long notAnyCategoryId : notAnyCategoryIds) {
389                            AssetCategory assetCategory =
390                                    AssetCategoryLocalServiceUtil.fetchAssetCategory(
391                                            notAnyCategoryId);
392    
393                            if (assetCategory == null) {
394                                    continue;
395                            }
396    
397                            List<Long> categoryIds = new ArrayList<Long>();
398    
399                            if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
400                                    categoryIds.addAll(
401                                            AssetCategoryLocalServiceUtil.getSubcategoryIds(
402                                                    notAnyCategoryId));
403                            }
404    
405                            if (categoryIds.isEmpty()) {
406                                    categoryIds.add(notAnyCategoryId);
407                            }
408    
409                            for (long categoryId : categoryIds) {
410                                    categoryIdsQuery.addTerm(Field.ASSET_CATEGORY_IDS, categoryId);
411                            }
412                    }
413    
414                    contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST_NOT);
415            }
416    
417            protected void addSearchNotAnyTags(
418                            BooleanQuery contextQuery, SearchContext searchContext)
419                    throws Exception {
420    
421                    long[] notAnyTagIds = _assetEntryQuery.getNotAnyTagIds();
422    
423                    if (notAnyTagIds.length == 0) {
424                            return;
425                    }
426    
427                    BooleanQuery tagIdsQuery = BooleanQueryFactoryUtil.create(
428                            searchContext);
429    
430                    for (long tagId : _assetEntryQuery.getNotAnyTagIds()) {
431                            tagIdsQuery.addTerm(Field.ASSET_TAG_IDS, tagId);
432                    }
433    
434                    contextQuery.add(tagIdsQuery, BooleanClauseOccur.MUST_NOT);
435            }
436    
437            @Override
438            protected void postProcessFullQuery(
439                            BooleanQuery fullQuery, SearchContext searchContext)
440                    throws Exception {
441    
442                    fullQuery.addRequiredTerm("visible", true);
443            }
444    
445            private AssetEntryQuery _assetEntryQuery;
446    
447    }