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[][] allTagIdsArray = _assetEntryQuery.getAllTagIdsArray();
145    
146                    if (allTagIdsArray.length == 0) {
147                            return;
148                    }
149    
150                    BooleanQuery tagIdsArrayQuery = BooleanQueryFactoryUtil.create(
151                            searchContext);
152    
153                    for (long[] allTagIds : allTagIdsArray) {
154                            if (allTagIds.length == 0) {
155                                    continue;
156                            }
157    
158                            long[] filteredAllTagIds = AssetUtil.filterTagIds(
159                                    permissionChecker, allTagIds);
160    
161                            if (allTagIds.length != filteredAllTagIds.length) {
162                                    addImpossibleTerm(contextQuery, Field.ASSET_TAG_IDS);
163    
164                                    return;
165                            }
166    
167                            BooleanQuery tagIdsQuery = BooleanQueryFactoryUtil.create(
168                                    searchContext);
169    
170                            for (long tagId : allTagIds) {
171                                    tagIdsQuery.addTerm(Field.ASSET_TAG_IDS, tagId);
172                            }
173    
174                            tagIdsArrayQuery.add(tagIdsQuery, BooleanClauseOccur.MUST);
175                    }
176    
177                    contextQuery.add(tagIdsArrayQuery, BooleanClauseOccur.MUST);
178            }
179    
180            protected void addSearchAnyCategories(
181                            BooleanQuery contextQuery, SearchContext searchContext)
182                    throws Exception {
183    
184                    PermissionChecker permissionChecker =
185                            PermissionThreadLocal.getPermissionChecker();
186    
187                    long[] anyCategoryIds = _assetEntryQuery.getAnyCategoryIds();
188    
189                    if (anyCategoryIds.length == 0) {
190                            return;
191                    }
192    
193                    long[] filteredAnyCategoryIds = AssetUtil.filterCategoryIds(
194                            permissionChecker, anyCategoryIds);
195    
196                    if (filteredAnyCategoryIds.length == 0) {
197                            addImpossibleTerm(contextQuery, Field.ASSET_CATEGORY_IDS);
198    
199                            return;
200                    }
201    
202                    BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create(
203                            searchContext);
204    
205                    for (long anyCategoryId : filteredAnyCategoryIds) {
206                            AssetCategory assetCategory =
207                                    AssetCategoryLocalServiceUtil.fetchAssetCategory(anyCategoryId);
208    
209                            if (assetCategory == null) {
210                                    continue;
211                            }
212    
213                            List<Long> categoryIds = new ArrayList<Long>();
214    
215                            if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
216                                    categoryIds.addAll(
217                                            AssetCategoryLocalServiceUtil.getSubcategoryIds(
218                                                    anyCategoryId));
219                            }
220    
221                            if (categoryIds.isEmpty()) {
222                                    categoryIds.add(anyCategoryId);
223                            }
224    
225                            for (long categoryId : categoryIds) {
226                                    categoryIdsQuery.addTerm(Field.ASSET_CATEGORY_IDS, categoryId);
227                            }
228                    }
229    
230                    contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
231            }
232    
233            protected void addSearchAnyTags(
234                            BooleanQuery contextQuery, SearchContext searchContext)
235                    throws Exception {
236    
237                    PermissionChecker permissionChecker =
238                            PermissionThreadLocal.getPermissionChecker();
239    
240                    long[] anyTagIds = _assetEntryQuery.getAnyTagIds();
241    
242                    if (anyTagIds.length == 0) {
243                            return;
244                    }
245    
246                    long[] filteredAnyTagIds = AssetUtil.filterTagIds(
247                            permissionChecker, anyTagIds);
248    
249                    if (filteredAnyTagIds.length == 0) {
250                            addImpossibleTerm(contextQuery, Field.ASSET_TAG_IDS);
251    
252                            return;
253                    }
254    
255                    BooleanQuery tagIdsQuery = BooleanQueryFactoryUtil.create(
256                            searchContext);
257    
258                    for (long tagId : anyTagIds) {
259                            tagIdsQuery.addTerm(Field.ASSET_TAG_IDS, tagId);
260                    }
261    
262                    contextQuery.add(tagIdsQuery, BooleanClauseOccur.MUST);
263            }
264    
265            @Override
266            protected void addSearchAssetCategoryIds(
267                            BooleanQuery contextQuery, SearchContext searchContext)
268                    throws Exception {
269    
270                    addSearchAllCategories(contextQuery, searchContext);
271                    addSearchAnyCategories(contextQuery, searchContext);
272                    addSearchNotAnyCategories(contextQuery, searchContext);
273                    addSearchNotAllCategories(contextQuery, searchContext);
274            }
275    
276            @Override
277            protected void addSearchAssetTagNames(
278                            BooleanQuery contextQuery, SearchContext searchContext)
279                    throws Exception {
280    
281                    addSearchAllTags(contextQuery, searchContext);
282                    addSearchAnyTags(contextQuery, searchContext);
283                    addSearchNotAllTags(contextQuery, searchContext);
284                    addSearchNotAnyTags(contextQuery, searchContext);
285            }
286    
287            @Override
288            protected void addSearchKeywords(
289                            BooleanQuery searchQuery, SearchContext searchContext)
290                    throws Exception {
291    
292                    String keywords = searchContext.getKeywords();
293    
294                    if (Validator.isNull(keywords)) {
295                            return;
296                    }
297    
298                    super.addSearchKeywords(searchQuery, searchContext);
299    
300                    String field = DocumentImpl.getLocalizedName(
301                            searchContext.getLocale(), "localized_title");
302    
303                    searchQuery.addTerm(field, keywords, true);
304            }
305    
306            @Override
307            protected void addSearchLayout(
308                            BooleanQuery contextQuery, SearchContext searchContext)
309                    throws Exception {
310    
311                    String layoutUuid = (String)searchContext.getAttribute(
312                            Field.LAYOUT_UUID);
313    
314                    if (Validator.isNotNull(layoutUuid)) {
315                            contextQuery.addRequiredTerm(Field.LAYOUT_UUID, layoutUuid);
316                    }
317            }
318    
319            protected void addSearchNotAllCategories(
320                            BooleanQuery contextQuery, SearchContext searchContext)
321                    throws Exception {
322    
323                    long[] notAllCategoryIds = _assetEntryQuery.getNotAllCategoryIds();
324    
325                    if (notAllCategoryIds.length == 0) {
326                            return;
327                    }
328    
329                    BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create(
330                            searchContext);
331    
332                    for (long notAllCategoryId : notAllCategoryIds) {
333                            AssetCategory assetCategory =
334                                    AssetCategoryLocalServiceUtil.fetchAssetCategory(
335                                            notAllCategoryId);
336    
337                            if (assetCategory == null) {
338                                    continue;
339                            }
340    
341                            List<Long> categoryIds = new ArrayList<Long>();
342    
343                            if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
344                                    categoryIds.addAll(
345                                            AssetCategoryLocalServiceUtil.getSubcategoryIds(
346                                                    notAllCategoryId));
347                            }
348    
349                            if (categoryIds.isEmpty()) {
350                                    categoryIds.add(notAllCategoryId);
351                            }
352    
353                            BooleanQuery categoryIdQuery = BooleanQueryFactoryUtil.create(
354                                    searchContext);
355    
356                            for (long categoryId : categoryIds) {
357                                    categoryIdQuery.addTerm(Field.ASSET_CATEGORY_IDS, categoryId);
358                            }
359    
360                            categoryIdsQuery.add(categoryIdQuery, BooleanClauseOccur.MUST);
361                    }
362    
363                    contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST_NOT);
364            }
365    
366            protected void addSearchNotAllTags(
367                            BooleanQuery contextQuery, SearchContext searchContext)
368                    throws Exception {
369    
370                    long[][] notAllTagIdsArray = _assetEntryQuery.getNotAllTagIdsArray();
371    
372                    if (notAllTagIdsArray.length == 0) {
373                            return;
374                    }
375    
376                    BooleanQuery tagIdsArrayQuery = BooleanQueryFactoryUtil.create(
377                            searchContext);
378    
379                    for (long[] notAllTagIds : notAllTagIdsArray) {
380                            if (notAllTagIds.length == 0) {
381                                    continue;
382                            }
383    
384                            BooleanQuery tagIdsQuery = BooleanQueryFactoryUtil.create(
385                                    searchContext);
386    
387                            for (long tagId : notAllTagIds) {
388                                    tagIdsQuery.addTerm(Field.ASSET_TAG_IDS, tagId);
389                            }
390    
391                            tagIdsArrayQuery.add(tagIdsQuery, BooleanClauseOccur.MUST);
392                    }
393    
394                    contextQuery.add(tagIdsArrayQuery, BooleanClauseOccur.MUST_NOT);
395            }
396    
397            protected void addSearchNotAnyCategories(
398                            BooleanQuery contextQuery, SearchContext searchContext)
399                    throws Exception {
400    
401                    long[] notAnyCategoryIds = _assetEntryQuery.getNotAnyCategoryIds();
402    
403                    if (notAnyCategoryIds.length == 0) {
404                            return;
405                    }
406    
407                    BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create(
408                            searchContext);
409    
410                    for (long notAnyCategoryId : notAnyCategoryIds) {
411                            AssetCategory assetCategory =
412                                    AssetCategoryLocalServiceUtil.fetchAssetCategory(
413                                            notAnyCategoryId);
414    
415                            if (assetCategory == null) {
416                                    continue;
417                            }
418    
419                            List<Long> categoryIds = new ArrayList<Long>();
420    
421                            if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
422                                    categoryIds.addAll(
423                                            AssetCategoryLocalServiceUtil.getSubcategoryIds(
424                                                    notAnyCategoryId));
425                            }
426    
427                            if (categoryIds.isEmpty()) {
428                                    categoryIds.add(notAnyCategoryId);
429                            }
430    
431                            for (long categoryId : categoryIds) {
432                                    categoryIdsQuery.addTerm(Field.ASSET_CATEGORY_IDS, categoryId);
433                            }
434                    }
435    
436                    contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST_NOT);
437            }
438    
439            protected void addSearchNotAnyTags(
440                            BooleanQuery contextQuery, SearchContext searchContext)
441                    throws Exception {
442    
443                    long[] notAnyTagIds = _assetEntryQuery.getNotAnyTagIds();
444    
445                    if (notAnyTagIds.length == 0) {
446                            return;
447                    }
448    
449                    BooleanQuery tagIdsQuery = BooleanQueryFactoryUtil.create(
450                            searchContext);
451    
452                    for (long tagId : _assetEntryQuery.getNotAnyTagIds()) {
453                            tagIdsQuery.addTerm(Field.ASSET_TAG_IDS, tagId);
454                    }
455    
456                    contextQuery.add(tagIdsQuery, BooleanClauseOccur.MUST_NOT);
457            }
458    
459            @Override
460            protected void postProcessFullQuery(
461                            BooleanQuery fullQuery, SearchContext searchContext)
462                    throws Exception {
463    
464                    fullQuery.addRequiredTerm("visible", true);
465            }
466    
467            private AssetEntryQuery _assetEntryQuery;
468    
469    }