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