001
014
015 package com.liferay.portal.kernel.search;
016
017 import com.liferay.portal.NoSuchCountryException;
018 import com.liferay.portal.NoSuchModelException;
019 import com.liferay.portal.NoSuchRegionException;
020 import com.liferay.portal.kernel.exception.PortalException;
021 import com.liferay.portal.kernel.language.LanguageUtil;
022 import com.liferay.portal.kernel.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.search.facet.AssetEntriesFacet;
025 import com.liferay.portal.kernel.search.facet.Facet;
026 import com.liferay.portal.kernel.search.facet.MultiValueFacet;
027 import com.liferay.portal.kernel.search.facet.ScopeFacet;
028 import com.liferay.portal.kernel.search.filter.BooleanFilter;
029 import com.liferay.portal.kernel.search.filter.Filter;
030 import com.liferay.portal.kernel.search.filter.QueryFilter;
031 import com.liferay.portal.kernel.search.filter.TermsFilter;
032 import com.liferay.portal.kernel.search.generic.BooleanQueryImpl;
033 import com.liferay.portal.kernel.search.generic.MatchAllQuery;
034 import com.liferay.portal.kernel.search.hits.HitsProcessor;
035 import com.liferay.portal.kernel.search.hits.HitsProcessorRegistryUtil;
036 import com.liferay.portal.kernel.trash.TrashHandler;
037 import com.liferay.portal.kernel.trash.TrashRenderer;
038 import com.liferay.portal.kernel.util.ArrayUtil;
039 import com.liferay.portal.kernel.util.GetterUtil;
040 import com.liferay.portal.kernel.util.ListUtil;
041 import com.liferay.portal.kernel.util.LocaleUtil;
042 import com.liferay.portal.kernel.util.LocalizationUtil;
043 import com.liferay.portal.kernel.util.PropsKeys;
044 import com.liferay.portal.kernel.util.PropsUtil;
045 import com.liferay.portal.kernel.util.SetUtil;
046 import com.liferay.portal.kernel.util.StringPool;
047 import com.liferay.portal.kernel.util.StringUtil;
048 import com.liferay.portal.kernel.util.UnicodeProperties;
049 import com.liferay.portal.kernel.util.Validator;
050 import com.liferay.portal.kernel.workflow.WorkflowConstants;
051 import com.liferay.portal.model.Address;
052 import com.liferay.portal.model.AttachedModel;
053 import com.liferay.portal.model.AuditedModel;
054 import com.liferay.portal.model.BaseModel;
055 import com.liferay.portal.model.Country;
056 import com.liferay.portal.model.Group;
057 import com.liferay.portal.model.GroupedModel;
058 import com.liferay.portal.model.Region;
059 import com.liferay.portal.model.ResourcedModel;
060 import com.liferay.portal.model.TrashedModel;
061 import com.liferay.portal.model.User;
062 import com.liferay.portal.model.WorkflowedModel;
063 import com.liferay.portal.security.permission.PermissionChecker;
064 import com.liferay.portal.security.permission.PermissionThreadLocal;
065 import com.liferay.portal.service.CountryServiceUtil;
066 import com.liferay.portal.service.GroupLocalServiceUtil;
067 import com.liferay.portal.service.RegionServiceUtil;
068 import com.liferay.portal.service.ServiceContext;
069 import com.liferay.portal.service.ServiceContextThreadLocal;
070 import com.liferay.portal.service.UserLocalServiceUtil;
071 import com.liferay.portal.util.PortalUtil;
072 import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
073 import com.liferay.portlet.asset.model.AssetCategory;
074 import com.liferay.portlet.asset.model.AssetEntry;
075 import com.liferay.portlet.asset.model.AssetRendererFactory;
076 import com.liferay.portlet.asset.model.AssetTag;
077 import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
078 import com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil;
079 import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
080 import com.liferay.portlet.expando.model.ExpandoBridge;
081 import com.liferay.portlet.expando.model.ExpandoColumn;
082 import com.liferay.portlet.expando.model.ExpandoColumnConstants;
083 import com.liferay.portlet.expando.service.ExpandoColumnLocalServiceUtil;
084 import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
085 import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
086 import com.liferay.portlet.ratings.model.RatingsStats;
087 import com.liferay.portlet.ratings.service.RatingsStatsLocalServiceUtil;
088 import com.liferay.portlet.trash.model.TrashEntry;
089
090 import java.io.Serializable;
091
092 import java.util.ArrayList;
093 import java.util.Collection;
094 import java.util.Collections;
095 import java.util.Date;
096 import java.util.HashMap;
097 import java.util.HashSet;
098 import java.util.List;
099 import java.util.Locale;
100 import java.util.Map;
101 import java.util.Set;
102
103 import javax.portlet.PortletRequest;
104 import javax.portlet.PortletResponse;
105
106
112 public abstract class BaseIndexer implements Indexer {
113
114 @Override
115 public void delete(long companyId, String uid) throws SearchException {
116 try {
117 SearchEngineUtil.deleteDocument(
118 getSearchEngineId(), companyId, uid, _commitImmediately);
119 }
120 catch (SearchException se) {
121 throw se;
122 }
123 catch (Exception e) {
124 throw new SearchException(e);
125 }
126 }
127
128 @Override
129 public void delete(Object obj) throws SearchException {
130 try {
131 doDelete(obj);
132 }
133 catch (SearchException se) {
134 throw se;
135 }
136 catch (Exception e) {
137 throw new SearchException(e);
138 }
139 }
140
141
144 @Deprecated
145 @Override
146 public String[] getClassNames() {
147 return getSearchClassNames();
148 }
149
150 @Override
151 public Document getDocument(Object obj) throws SearchException {
152 try {
153 Document document = doGetDocument(obj);
154
155 for (IndexerPostProcessor indexerPostProcessor :
156 _indexerPostProcessors) {
157
158 indexerPostProcessor.postProcessDocument(document, obj);
159 }
160
161 if (document == null) {
162 return null;
163 }
164
165 Map<String, Field> fields = document.getFields();
166
167 Field groupIdField = fields.get(Field.GROUP_ID);
168
169 if (groupIdField != null) {
170 long groupId = GetterUtil.getLong(groupIdField.getValue());
171
172 addStagingGroupKeyword(document, groupId);
173 }
174
175 return document;
176 }
177 catch (SearchException se) {
178 throw se;
179 }
180 catch (Exception e) {
181 throw new SearchException(e);
182 }
183 }
184
185 @Override
186 public BooleanFilter getFacetBooleanFilter(
187 String className, SearchContext searchContext)
188 throws Exception {
189
190 BooleanFilter facetBooleanFilter = new BooleanFilter();
191
192 facetBooleanFilter.addTerm(Field.ENTRY_CLASS_NAME, className);
193
194 if (searchContext.getUserId() > 0) {
195 SearchPermissionChecker searchPermissionChecker =
196 SearchEngineUtil.getSearchPermissionChecker();
197
198 long[] groupIds = searchContext.getGroupIds();
199
200 long groupId = GetterUtil.getLong(
201 searchContext.getAttribute("groupId"));
202
203 if (groupId > 0) {
204 groupIds = new long[] {groupId};
205 }
206
207 facetBooleanFilter =
208 searchPermissionChecker.getPermissionBooleanFilter(
209 searchContext.getCompanyId(), groupIds,
210 searchContext.getUserId(), className, facetBooleanFilter,
211 searchContext);
212 }
213
214 return facetBooleanFilter;
215 }
216
217 @Override
218 public BooleanQuery getFullQuery(SearchContext searchContext)
219 throws SearchException {
220
221 try {
222 searchContext.setSearchEngineId(getSearchEngineId());
223
224 resetFullQuery(searchContext);
225
226 String[] fullQueryEntryClassNames =
227 searchContext.getFullQueryEntryClassNames();
228
229 if (ArrayUtil.isNotEmpty(fullQueryEntryClassNames)) {
230 searchContext.setAttribute(
231 "relatedEntryClassNames", getSearchClassNames());
232 }
233
234 String[] entryClassNames = ArrayUtil.append(
235 getSearchClassNames(), fullQueryEntryClassNames);
236
237 searchContext.setEntryClassNames(entryClassNames);
238
239 BooleanFilter fullQueryBooleanFilter = new BooleanFilter();
240
241 addSearchAssetCategoryIds(fullQueryBooleanFilter, searchContext);
242 addSearchAssetTagNames(fullQueryBooleanFilter, searchContext);
243 addSearchEntryClassNames(fullQueryBooleanFilter, searchContext);
244 addSearchFolderId(fullQueryBooleanFilter, searchContext);
245 addSearchGroupId(fullQueryBooleanFilter, searchContext);
246 addSearchLayout(fullQueryBooleanFilter, searchContext);
247 addSearchUserId(fullQueryBooleanFilter, searchContext);
248
249 BooleanQuery fullQuery = createFullQuery(
250 fullQueryBooleanFilter, searchContext);
251
252 fullQuery.setQueryConfig(searchContext.getQueryConfig());
253
254 return fullQuery;
255 }
256 catch (SearchException se) {
257 throw se;
258 }
259 catch (Exception e) {
260 throw new SearchException(e);
261 }
262 }
263
264 @Override
265 public IndexerPostProcessor[] getIndexerPostProcessors() {
266 return _indexerPostProcessors;
267 }
268
269
272 @Deprecated
273 @Override
274 public String getPortletId() {
275 return StringPool.BLANK;
276 }
277
278 @Override
279 public String[] getSearchClassNames() {
280 return new String[] {getClassName()};
281 }
282
283 @Override
284 public String getSearchEngineId() {
285 if (_searchEngineId != null) {
286 return _searchEngineId;
287 }
288
289 Class<?> clazz = getClass();
290
291 String searchEngineId = GetterUtil.getString(
292 PropsUtil.get(
293 PropsKeys.INDEX_SEARCH_ENGINE_ID,
294 new com.liferay.portal.kernel.configuration.Filter(
295 clazz.getName())));
296
297 if (Validator.isNotNull(searchEngineId)) {
298 SearchEngine searchEngine = SearchEngineUtil.getSearchEngine(
299 searchEngineId);
300
301 if (searchEngine != null) {
302 _searchEngineId = searchEngineId;
303 }
304 }
305
306 if (_searchEngineId == null) {
307 _searchEngineId = SearchEngineUtil.getDefaultSearchEngineId();
308 }
309
310 if (_log.isDebugEnabled()) {
311 _log.debug(
312 "Search engine ID for " + clazz.getName() + " is " +
313 searchEngineId);
314 }
315
316 return _searchEngineId;
317 }
318
319 @Override
320 public String getSortField(String orderByCol) {
321 String sortField = doGetSortField(orderByCol);
322
323 if (_document.isDocumentSortableTextField(sortField)) {
324 return DocumentImpl.getSortableFieldName(sortField);
325 }
326
327 return sortField;
328 }
329
330 @Override
331 public String getSortField(String orderByCol, int sortType) {
332 if ((sortType == Sort.DOUBLE_TYPE) || (sortType == Sort.FLOAT_TYPE) ||
333 (sortType == Sort.INT_TYPE) || (sortType == Sort.LONG_TYPE)) {
334
335 return DocumentImpl.getSortableFieldName(orderByCol);
336 }
337
338 return getSortField(orderByCol);
339 }
340
341
345 @Deprecated
346 @Override
347 public Summary getSummary(Document document, Locale locale, String snippet)
348 throws SearchException {
349
350 return getSummary(document, snippet, null, null);
351 }
352
353 @Override
354 public Summary getSummary(
355 Document document, String snippet, PortletRequest portletRequest,
356 PortletResponse portletResponse)
357 throws SearchException {
358
359 try {
360 Locale locale = getLocale(portletRequest);
361
362 Summary summary = doGetSummary(
363 document, locale, snippet, portletRequest, portletResponse);
364
365 for (IndexerPostProcessor indexerPostProcessor :
366 _indexerPostProcessors) {
367
368 indexerPostProcessor.postProcessSummary(
369 summary, document, locale, snippet);
370 }
371
372 return summary;
373 }
374 catch (SearchException se) {
375 throw se;
376 }
377 catch (Exception e) {
378 throw new SearchException(e);
379 }
380 }
381
382 @Override
383 public boolean hasPermission(
384 PermissionChecker permissionChecker, String entryClassName,
385 long entryClassPK, String actionId)
386 throws Exception {
387
388 return true;
389 }
390
391 @Override
392 public boolean isCommitImmediately() {
393 return _commitImmediately;
394 }
395
396 @Override
397 public boolean isFilterSearch() {
398 return _filterSearch;
399 }
400
401 public boolean isIndexerEnabled() {
402 return _indexerEnabled;
403 }
404
405 @Override
406 public boolean isPermissionAware() {
407 return _permissionAware;
408 }
409
410 public boolean isSelectAllLocales() {
411 return _selectAllLocales;
412 }
413
414 @Override
415 public boolean isStagingAware() {
416 return _stagingAware;
417 }
418
419 @Override
420 public boolean isVisible(long classPK, int status) throws Exception {
421 return true;
422 }
423
424 @Override
425 public boolean isVisibleRelatedEntry(long classPK, int status)
426 throws Exception {
427
428 return true;
429 }
430
431 @Override
432 public void postProcessContextBooleanFilter(
433 BooleanFilter contextBooleanFilter, SearchContext searchContext)
434 throws Exception {
435 }
436
437
441 @Deprecated
442 @Override
443 public void postProcessContextQuery(
444 BooleanQuery contextQuery, SearchContext searchContext)
445 throws Exception {
446 }
447
448 @Override
449 public void postProcessSearchQuery(
450 BooleanQuery searchQuery, BooleanFilter fullQueryBooleanFilter,
451 SearchContext searchContext)
452 throws Exception {
453
454 String keywords = searchContext.getKeywords();
455
456 if (Validator.isNull(keywords)) {
457 addSearchTerm(searchQuery, searchContext, Field.DESCRIPTION, false);
458 addSearchTerm(searchQuery, searchContext, Field.TITLE, false);
459 addSearchTerm(searchQuery, searchContext, Field.USER_NAME, false);
460 }
461 }
462
463
467 @Deprecated
468 @Override
469 public void postProcessSearchQuery(
470 BooleanQuery searchQuery, SearchContext searchContext)
471 throws Exception {
472 }
473
474 @Override
475 public void registerIndexerPostProcessor(
476 IndexerPostProcessor indexerPostProcessor) {
477
478 List<IndexerPostProcessor> indexerPostProcessorsList =
479 ListUtil.fromArray(_indexerPostProcessors);
480
481 indexerPostProcessorsList.add(indexerPostProcessor);
482
483 _indexerPostProcessors = indexerPostProcessorsList.toArray(
484 new IndexerPostProcessor[indexerPostProcessorsList.size()]);
485 }
486
487 @Override
488 public void reindex(Object obj) throws SearchException {
489 try {
490 if (SearchEngineUtil.isIndexReadOnly() || !isIndexerEnabled()) {
491 return;
492 }
493
494 if (obj instanceof List<?>) {
495 List<?> list = (List<?>)obj;
496
497 for (Object element : list) {
498 doReindex(element);
499 }
500 }
501 else {
502 doReindex(obj);
503 }
504 }
505 catch (SearchException se) {
506 throw se;
507 }
508 catch (Exception e) {
509 throw new SearchException(e);
510 }
511 }
512
513 @Override
514 public void reindex(String className, long classPK) throws SearchException {
515 try {
516 if (SearchEngineUtil.isIndexReadOnly() || !isIndexerEnabled() ||
517 (classPK <= 0)) {
518
519 return;
520 }
521
522 doReindex(className, classPK);
523 }
524 catch (NoSuchModelException nsme) {
525 if (_log.isWarnEnabled()) {
526 _log.warn("Unable to index " + className + " " + classPK, nsme);
527 }
528 }
529 catch (SearchException se) {
530 throw se;
531 }
532 catch (Exception e) {
533 throw new SearchException(e);
534 }
535 }
536
537 @Override
538 public void reindex(String[] ids) throws SearchException {
539 try {
540 if (SearchEngineUtil.isIndexReadOnly() || !isIndexerEnabled()) {
541 return;
542 }
543
544 doReindex(ids);
545 }
546 catch (SearchException se) {
547 throw se;
548 }
549 catch (Exception e) {
550 throw new SearchException(e);
551 }
552 }
553
554 @Override
555 public Hits search(SearchContext searchContext) throws SearchException {
556 try {
557 Hits hits = null;
558
559 QueryConfig queryConfig = searchContext.getQueryConfig();
560
561 addDefaultHighlightFieldNames(queryConfig);
562
563 if (ArrayUtil.isEmpty(queryConfig.getSelectedFieldNames())) {
564 addDefaultSelectedFieldNames(searchContext);
565 }
566
567 addFacetSelectedFieldNames(searchContext, queryConfig);
568
569 PermissionChecker permissionChecker =
570 PermissionThreadLocal.getPermissionChecker();
571
572 if ((permissionChecker != null) &&
573 isUseSearchResultPermissionFilter(searchContext)) {
574
575 SearchResultPermissionFilter searchResultPermissionFilter =
576 new DefaultSearchResultPermissionFilter(
577 this, permissionChecker);
578
579 hits = searchResultPermissionFilter.search(searchContext);
580 }
581 else {
582 hits = doSearch(searchContext);
583 }
584
585 processHits(searchContext, hits);
586
587 return hits;
588 }
589 catch (SearchException se) {
590 throw se;
591 }
592 catch (Exception e) {
593 throw new SearchException(e);
594 }
595 }
596
597 @Override
598 public Hits search(
599 SearchContext searchContext, String... selectedFieldNames)
600 throws SearchException {
601
602 QueryConfig queryConfig = searchContext.getQueryConfig();
603
604 queryConfig.setSelectedFieldNames(selectedFieldNames);
605
606 return search(searchContext);
607 }
608
609 @Override
610 public long searchCount(SearchContext searchContext)
611 throws SearchException {
612
613 PermissionChecker permissionChecker =
614 PermissionThreadLocal.getPermissionChecker();
615
616 if ((permissionChecker != null) &&
617 isUseSearchResultPermissionFilter(searchContext)) {
618
619 Hits hits = search(searchContext);
620
621 return hits.getLength();
622 }
623
624 QueryConfig queryConfig = searchContext.getQueryConfig();
625
626 queryConfig.setHighlightEnabled(false);
627 queryConfig.setHitsProcessingEnabled(false);
628 queryConfig.setScoreEnabled(false);
629 queryConfig.setQueryIndexingEnabled(false);
630 queryConfig.setQuerySuggestionEnabled(false);
631
632 searchContext.setSearchEngineId(getSearchEngineId());
633
634 BooleanQuery fullQuery = getFullQuery(searchContext);
635
636 fullQuery.setQueryConfig(queryConfig);
637
638 return SearchEngineUtil.searchCount(searchContext, fullQuery);
639 }
640
641 public void setCommitImmediately(boolean commitImmediately) {
642 _commitImmediately = commitImmediately;
643 }
644
645 public void setSelectAllLocales(boolean selectAllLocales) {
646 _selectAllLocales = selectAllLocales;
647 }
648
649 @Override
650 public void unregisterIndexerPostProcessor(
651 IndexerPostProcessor indexerPostProcessor) {
652
653 List<IndexerPostProcessor> indexerPostProcessorsList =
654 ListUtil.fromArray(_indexerPostProcessors);
655
656 indexerPostProcessorsList.remove(indexerPostProcessor);
657
658 _indexerPostProcessors = indexerPostProcessorsList.toArray(
659 new IndexerPostProcessor[indexerPostProcessorsList.size()]);
660 }
661
662 protected void addAssetFields(
663 Document document, String className, long classPK) {
664
665 AssetRendererFactory assetRendererFactory =
666 AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClassName(
667 className);
668
669 if ((assetRendererFactory == null) ||
670 !assetRendererFactory.isSelectable()) {
671
672 return;
673 }
674
675 AssetEntry assetEntry = AssetEntryLocalServiceUtil.fetchEntry(
676 className, classPK);
677
678 if (assetEntry == null) {
679 return;
680 }
681
682 if (!document.hasField(Field.CREATE_DATE)) {
683 document.addDate(Field.CREATE_DATE, assetEntry.getCreateDate());
684 }
685
686 if (assetEntry.getExpirationDate() != null) {
687 document.addDate(
688 Field.EXPIRATION_DATE, assetEntry.getExpirationDate());
689 }
690 else {
691 document.addDate(Field.EXPIRATION_DATE, new Date(Long.MAX_VALUE));
692 }
693
694 if (!document.hasField(Field.MODIFIED_DATE)) {
695 document.addDate(Field.MODIFIED_DATE, assetEntry.getModifiedDate());
696 }
697
698 document.addNumber(Field.PRIORITY, assetEntry.getPriority());
699
700 if (assetEntry.getPublishDate() != null) {
701 document.addDate(Field.PUBLISH_DATE, assetEntry.getPublishDate());
702 }
703 else {
704 document.addDate(Field.PUBLISH_DATE, new Date(0));
705 }
706
707 RatingsStats ratingsStats = RatingsStatsLocalServiceUtil.getStats(
708 className, classPK);
709
710 document.addNumber(Field.RATINGS, ratingsStats.getAverageScore());
711
712 document.addNumber(Field.VIEW_COUNT, assetEntry.getViewCount());
713
714 document.addLocalizedKeyword(
715 "localized_title",
716 populateMap(assetEntry, assetEntry.getTitleMap()), true, true);
717 document.addKeyword("visible", assetEntry.isVisible());
718 }
719
720 protected void addDefaultHighlightFieldNames(QueryConfig queryConfig) {
721 queryConfig.addHighlightFieldNames(Field.ASSET_CATEGORY_TITLES);
722
723 if (queryConfig.isHighlightEnabled()) {
724 queryConfig.addHighlightFieldNames(
725 Field.CONTENT, Field.DESCRIPTION, Field.TITLE);
726 }
727 }
728
729 protected void addDefaultSelectedFieldNames(SearchContext searchContext) {
730 QueryConfig queryConfig = searchContext.getQueryConfig();
731
732 Set<String> selectedFieldNames = null;
733
734 if (!ArrayUtil.isEmpty(getDefaultSelectedFieldNames())) {
735 selectedFieldNames = SetUtil.fromArray(
736 getDefaultSelectedFieldNames());
737
738 if (searchContext.isIncludeAttachments() ||
739 searchContext.isIncludeDiscussions()) {
740
741 selectedFieldNames.add(Field.CLASS_NAME_ID);
742 selectedFieldNames.add(Field.CLASS_PK);
743 }
744 }
745
746 if (!ArrayUtil.isEmpty(getDefaultSelectedLocalizedFieldNames())) {
747 if (selectedFieldNames == null) {
748 selectedFieldNames = new HashSet<>();
749 }
750
751 if (isSelectAllLocales()) {
752 addSelectedLocalizedFieldNames(
753 selectedFieldNames,
754 LocaleUtil.toLanguageIds(
755 LanguageUtil.getSupportedLocales()));
756 }
757 else {
758 addSelectedLocalizedFieldNames(
759 selectedFieldNames,
760 LocaleUtil.toLanguageId(queryConfig.getLocale()));
761 }
762 }
763
764 if ((selectedFieldNames != null) && !selectedFieldNames.isEmpty()) {
765 queryConfig.setSelectedFieldNames(
766 selectedFieldNames.toArray(
767 new String[selectedFieldNames.size()]));
768 }
769 }
770
771
774 @Deprecated
775 protected void addFacetClause(
776 SearchContext searchContext, BooleanFilter facetBooleanFilter,
777 Collection<Facet> facets)
778 throws ParseException {
779
780 BooleanQuery facetBooleanQuery = new BooleanQueryImpl();
781
782 for (Facet facet : facets) {
783 BooleanClause<Query> facetBooleanClause = facet.getFacetClause();
784
785 if (facetBooleanClause != null) {
786 facetBooleanQuery.add(
787 facetBooleanClause.getClause(),
788 facetBooleanClause.getBooleanClauseOccur());
789 }
790 }
791
792 if (!facetBooleanQuery.hasClauses()) {
793 return;
794 }
795
796 QueryFilter queryFilter = new QueryFilter(facetBooleanQuery);
797
798 facetBooleanFilter.add(queryFilter, BooleanClauseOccur.MUST);
799 }
800
801 protected void addFacetSelectedFieldNames(
802 SearchContext searchContext, QueryConfig queryConfig) {
803
804 String[] selectedFieldNames = queryConfig.getSelectedFieldNames();
805
806 if (ArrayUtil.isEmpty(selectedFieldNames) ||
807 (selectedFieldNames.length == 1) &&
808 selectedFieldNames[0].equals(Field.ANY)) {
809
810 return;
811 }
812
813 Set<String> selectedFieldNameSet = SetUtil.fromArray(
814 selectedFieldNames);
815
816 Map<String, Facet> facets = searchContext.getFacets();
817
818 selectedFieldNameSet.addAll(facets.keySet());
819
820 selectedFieldNames = selectedFieldNameSet.toArray(
821 new String[selectedFieldNameSet.size()]);
822
823 queryConfig.setSelectedFieldNames(selectedFieldNames);
824 }
825
826 protected void addSearchAssetCategoryIds(
827 BooleanFilter queryBooleanFilter, SearchContext searchContext)
828 throws Exception {
829
830 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
831
832 multiValueFacet.setFieldName(Field.ASSET_CATEGORY_IDS);
833 multiValueFacet.setStatic(true);
834 multiValueFacet.setValues(searchContext.getAssetCategoryIds());
835
836 searchContext.addFacet(multiValueFacet);
837 }
838
839 protected void addSearchAssetCategoryTitles(
840 Document document, String field, List<AssetCategory> assetCategories) {
841
842 Map<Locale, List<String>> assetCategoryTitles = new HashMap<>();
843
844 Locale defaultLocale = LocaleUtil.getDefault();
845
846 for (AssetCategory assetCategory : assetCategories) {
847 Map<Locale, String> titleMap = assetCategory.getTitleMap();
848
849 for (Map.Entry<Locale, String> entry : titleMap.entrySet()) {
850 Locale locale = entry.getKey();
851 String title = entry.getValue();
852
853 if (Validator.isNull(title)) {
854 continue;
855 }
856
857 List<String> titles = assetCategoryTitles.get(locale);
858
859 if (titles == null) {
860 titles = new ArrayList<>();
861
862 assetCategoryTitles.put(locale, titles);
863 }
864
865 titles.add(StringUtil.toLowerCase(title));
866 }
867 }
868
869 for (Map.Entry<Locale, List<String>> entry :
870 assetCategoryTitles.entrySet()) {
871
872 Locale locale = entry.getKey();
873 List<String> titles = entry.getValue();
874
875 String[] titlesArray = titles.toArray(new String[titles.size()]);
876
877 if (locale.equals(defaultLocale)) {
878 document.addText(field, titlesArray);
879 }
880
881 document.addText(
882 field.concat(StringPool.UNDERLINE).concat(locale.toString()),
883 titlesArray);
884 }
885 }
886
887 protected void addSearchAssetTagNames(
888 BooleanFilter queryBooleanFilter, SearchContext searchContext)
889 throws Exception {
890
891 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
892
893 multiValueFacet.setFieldName(Field.ASSET_TAG_NAMES);
894 multiValueFacet.setStatic(true);
895 multiValueFacet.setValues(searchContext.getAssetTagNames());
896
897 searchContext.addFacet(multiValueFacet);
898 }
899
900 protected Filter addSearchClassTypeIds(
901 BooleanFilter contextBooleanFilter, SearchContext searchContext)
902 throws Exception {
903
904 long[] classTypeIds = searchContext.getClassTypeIds();
905
906 if (ArrayUtil.isEmpty(classTypeIds)) {
907 return null;
908 }
909
910 TermsFilter classTypeIdsTermsFilter = new TermsFilter(
911 Field.CLASS_TYPE_ID);
912
913 classTypeIdsTermsFilter.addValues(
914 ArrayUtil.toStringArray(classTypeIds));
915
916 return contextBooleanFilter.add(
917 classTypeIdsTermsFilter, BooleanClauseOccur.MUST);
918 }
919
920 protected void addSearchEntryClassNames(
921 BooleanFilter queryBooleanFilter, SearchContext searchContext)
922 throws Exception {
923
924 Facet facet = new AssetEntriesFacet(searchContext);
925
926 facet.setStatic(true);
927
928 searchContext.addFacet(facet);
929 }
930
931 protected Map<String, Query> addSearchExpando(
932 BooleanQuery searchQuery, SearchContext searchContext,
933 String keywords)
934 throws Exception {
935
936 Map<String, Query> expandoQueries = new HashMap<>();
937
938 ExpandoBridge expandoBridge = ExpandoBridgeFactoryUtil.getExpandoBridge(
939 searchContext.getCompanyId(), getClassName(searchContext));
940
941 Set<String> attributeNames = SetUtil.fromEnumeration(
942 expandoBridge.getAttributeNames());
943
944 for (String attributeName : attributeNames) {
945 UnicodeProperties properties = expandoBridge.getAttributeProperties(
946 attributeName);
947
948 int indexType = GetterUtil.getInteger(
949 properties.getProperty(ExpandoColumnConstants.INDEX_TYPE));
950
951 if (indexType != ExpandoColumnConstants.INDEX_TYPE_NONE) {
952 String fieldName = getExpandoFieldName(
953 searchContext, expandoBridge, attributeName);
954
955 if (Validator.isNotNull(keywords)) {
956 if (searchContext.isAndSearch()) {
957 Query query = searchQuery.addRequiredTerm(
958 fieldName, keywords);
959
960 expandoQueries.put(attributeName, query);
961 }
962 else {
963 Query query = searchQuery.addTerm(fieldName, keywords);
964
965 expandoQueries.put(attributeName, query);
966 }
967 }
968 }
969 }
970
971 return expandoQueries;
972 }
973
974 protected void addSearchFolderId(
975 BooleanFilter queryBooleanFilter, SearchContext searchContext)
976 throws Exception {
977
978 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
979
980 multiValueFacet.setFieldName(Field.TREE_PATH);
981 multiValueFacet.setStatic(true);
982
983 long[] folderIds = searchContext.getFolderIds();
984
985 if (ArrayUtil.isNotEmpty(folderIds)) {
986 folderIds = ArrayUtil.remove(folderIds, _DEFAULT_FOLDER_ID);
987
988 multiValueFacet.setValues(folderIds);
989 }
990
991 searchContext.addFacet(multiValueFacet);
992 }
993
994 protected void addSearchGroupId(
995 BooleanFilter queryBooleanFilter, SearchContext searchContext)
996 throws Exception {
997
998 Facet facet = new ScopeFacet(searchContext);
999
1000 facet.setStatic(true);
1001
1002 searchContext.addFacet(facet);
1003 }
1004
1005 protected Map<String, Query> addSearchKeywords(
1006 BooleanQuery searchQuery, SearchContext searchContext)
1007 throws Exception {
1008
1009 String keywords = searchContext.getKeywords();
1010
1011 if (Validator.isNull(keywords)) {
1012 return Collections.emptyMap();
1013 }
1014
1015 addSearchExpando(searchQuery, searchContext, keywords);
1016
1017 addSearchLocalizedTerm(
1018 searchQuery, searchContext, Field.ASSET_CATEGORY_TITLES,
1019 searchContext.isLike());
1020
1021 return searchQuery.addTerms(
1022 Field.KEYWORDS, keywords, searchContext.isLike());
1023 }
1024
1025 protected void addSearchLayout(
1026 BooleanFilter queryBooleanFilter, SearchContext searchContext)
1027 throws Exception {
1028
1029 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
1030
1031 multiValueFacet.setFieldName(Field.LAYOUT_UUID);
1032 multiValueFacet.setStatic(true);
1033
1034 searchContext.addFacet(multiValueFacet);
1035 }
1036
1037 protected Map<String, Query> addSearchLocalizedTerm(
1038 BooleanQuery searchQuery, SearchContext searchContext, String field,
1039 boolean like)
1040 throws Exception {
1041
1042 Map<String, Query> queries = new HashMap<>();
1043
1044 Query query = addSearchTerm(searchQuery, searchContext, field, like);
1045
1046 queries.put(field, query);
1047
1048 String localizedFieldName = DocumentImpl.getLocalizedName(
1049 searchContext.getLocale(), field);
1050
1051 Query localizedQuery = addSearchTerm(
1052 searchQuery, searchContext, localizedFieldName, like);
1053
1054 queries.put(localizedFieldName, localizedQuery);
1055
1056 return queries;
1057 }
1058
1059 protected Query addSearchTerm(
1060 BooleanQuery searchQuery, SearchContext searchContext, String field,
1061 boolean like)
1062 throws Exception {
1063
1064 if (Validator.isNull(field)) {
1065 return null;
1066 }
1067
1068 String value = null;
1069
1070 Serializable serializable = searchContext.getAttribute(field);
1071
1072 if (serializable != null) {
1073 Class<?> clazz = serializable.getClass();
1074
1075 if (clazz.isArray()) {
1076 value = StringUtil.merge((Object[])serializable);
1077 }
1078 else {
1079 value = GetterUtil.getString(serializable);
1080 }
1081 }
1082 else {
1083 value = GetterUtil.getString(serializable);
1084 }
1085
1086 if (Validator.isNotNull(value) &&
1087 (searchContext.getFacet(field) != null)) {
1088
1089 return null;
1090 }
1091
1092 if (Validator.isNull(value)) {
1093 value = searchContext.getKeywords();
1094 }
1095
1096 if (Validator.isNull(value)) {
1097 return null;
1098 }
1099
1100 Query query = null;
1101
1102 if (searchContext.isAndSearch()) {
1103 query = searchQuery.addRequiredTerm(field, value, like);
1104 }
1105 else {
1106 query = searchQuery.addTerm(field, value, like);
1107 }
1108
1109 return query;
1110 }
1111
1112 protected void addSearchUserId(
1113 BooleanFilter queryBooleanFilter, SearchContext searchContext)
1114 throws Exception {
1115
1116 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
1117
1118 multiValueFacet.setFieldName(Field.USER_ID);
1119 multiValueFacet.setStatic(true);
1120
1121 long userId = GetterUtil.getLong(
1122 searchContext.getAttribute(Field.USER_ID));
1123
1124 if (userId > 0) {
1125 multiValueFacet.setValues(new long[] {userId});
1126 }
1127
1128 searchContext.addFacet(multiValueFacet);
1129 }
1130
1131 protected void addSelectedLocalizedFieldNames(
1132 Set<String> selectedFieldNames, String... languageIds) {
1133
1134 for (String defaultLocalizedSelectedFieldName :
1135 getDefaultSelectedLocalizedFieldNames()) {
1136
1137 selectedFieldNames.add(defaultLocalizedSelectedFieldName);
1138
1139 for (String languageId : languageIds) {
1140 String localizedFieldName = LocalizationUtil.getLocalizedName(
1141 defaultLocalizedSelectedFieldName, languageId);
1142
1143 selectedFieldNames.add(localizedFieldName);
1144 }
1145 }
1146 }
1147
1148 protected void addStagingGroupKeyword(Document document, long groupId) {
1149 if (!isStagingAware()) {
1150 return;
1151 }
1152
1153 document.addKeyword(Field.STAGING_GROUP, isStagingGroup(groupId));
1154 }
1155
1156 protected void addStatus(
1157 BooleanFilter contextBooleanFilter, SearchContext searchContext)
1158 throws Exception {
1159
1160 int status = GetterUtil.getInteger(
1161 searchContext.getAttribute(Field.STATUS),
1162 WorkflowConstants.STATUS_APPROVED);
1163
1164 if (status != WorkflowConstants.STATUS_ANY) {
1165 contextBooleanFilter.addRequiredTerm(Field.STATUS, status);
1166 }
1167 else {
1168 contextBooleanFilter.addTerm(
1169 Field.STATUS, String.valueOf(WorkflowConstants.STATUS_IN_TRASH),
1170 BooleanClauseOccur.MUST_NOT);
1171 }
1172 }
1173
1174 protected void addTrashFields(
1175 Document document, TrashedModel trashedModel) {
1176
1177 TrashEntry trashEntry = null;
1178
1179 try {
1180 trashEntry = trashedModel.getTrashEntry();
1181 }
1182 catch (PortalException pe) {
1183 if (_log.isDebugEnabled()) {
1184 _log.debug("Unable to get trash entry for " + trashedModel);
1185 }
1186 }
1187
1188 if (trashEntry == null) {
1189 document.addDate(Field.REMOVED_DATE, new Date());
1190
1191 ServiceContext serviceContext =
1192 ServiceContextThreadLocal.getServiceContext();
1193
1194 if (serviceContext != null) {
1195 try {
1196 User user = UserLocalServiceUtil.getUser(
1197 serviceContext.getUserId());
1198
1199 document.addKeyword(
1200 Field.REMOVED_BY_USER_NAME, user.getFullName(), true);
1201 }
1202 catch (PortalException pe) {
1203 if (_log.isDebugEnabled()) {
1204 _log.debug(
1205 "Unable to locate user: " +
1206 serviceContext.getUserId(),
1207 pe);
1208 }
1209 }
1210 }
1211 }
1212 else {
1213 document.addDate(Field.REMOVED_DATE, trashEntry.getCreateDate());
1214 document.addKeyword(
1215 Field.REMOVED_BY_USER_NAME, trashEntry.getUserName(), true);
1216
1217 if (trashedModel.isInTrash() &&
1218 !trashedModel.isInTrashExplicitly()) {
1219
1220 document.addKeyword(
1221 Field.ROOT_ENTRY_CLASS_NAME, trashEntry.getClassName());
1222 document.addKeyword(
1223 Field.ROOT_ENTRY_CLASS_PK, trashEntry.getClassPK());
1224 }
1225 }
1226
1227 TrashHandler trashHandler = trashedModel.getTrashHandler();
1228
1229 try {
1230 TrashRenderer trashRenderer = null;
1231
1232 if ((trashHandler != null) && (trashEntry != null)) {
1233 trashRenderer = trashHandler.getTrashRenderer(
1234 trashEntry.getClassPK());
1235 }
1236
1237 if (trashRenderer != null) {
1238 document.addKeyword(Field.TYPE, trashRenderer.getType(), true);
1239 }
1240 }
1241 catch (PortalException pe) {
1242 if (_log.isDebugEnabled()) {
1243 _log.debug(
1244 "Unable to get trash renderer for " +
1245 trashEntry.getClassName());
1246 }
1247 }
1248 }
1249
1250 protected BooleanQuery createFullQuery(
1251 BooleanFilter fullQueryBooleanFilter, SearchContext searchContext)
1252 throws Exception {
1253
1254 BooleanQuery searchQuery = new BooleanQueryImpl();
1255
1256 addSearchKeywords(searchQuery, searchContext);
1257 postProcessSearchQuery(
1258 searchQuery, fullQueryBooleanFilter, searchContext);
1259
1260 for (IndexerPostProcessor indexerPostProcessor :
1261 _indexerPostProcessors) {
1262
1263 indexerPostProcessor.postProcessSearchQuery(
1264 searchQuery, fullQueryBooleanFilter, searchContext);
1265 }
1266
1267 doPostProcessSearchQuery(this, searchQuery, searchContext);
1268
1269 Map<String, Facet> facets = searchContext.getFacets();
1270
1271 BooleanFilter facetBooleanFilter = new BooleanFilter();
1272
1273 for (Facet facet : facets.values()) {
1274 BooleanClause<Filter> filterBooleanClause =
1275 facet.getFacetFilterBooleanClause();
1276
1277 if (filterBooleanClause != null) {
1278 facetBooleanFilter.add(
1279 filterBooleanClause.getClause(),
1280 filterBooleanClause.getBooleanClauseOccur());
1281 }
1282 }
1283
1284 addFacetClause(searchContext, facetBooleanFilter, facets.values());
1285
1286 if (facetBooleanFilter.hasClauses()) {
1287 fullQueryBooleanFilter.add(
1288 facetBooleanFilter, BooleanClauseOccur.MUST);
1289 }
1290
1291 BooleanQuery fullBooleanQuery = new BooleanQueryImpl();
1292
1293 if (fullQueryBooleanFilter.hasClauses()) {
1294 fullBooleanQuery.setPreBooleanFilter(fullQueryBooleanFilter);
1295 }
1296
1297 if (searchQuery.hasClauses()) {
1298 fullBooleanQuery.add(searchQuery, BooleanClauseOccur.MUST);
1299 }
1300
1301 BooleanClause<Query>[] booleanClauses =
1302 searchContext.getBooleanClauses();
1303
1304 if (booleanClauses != null) {
1305 for (BooleanClause<Query> booleanClause : booleanClauses) {
1306 fullBooleanQuery.add(
1307 booleanClause.getClause(),
1308 booleanClause.getBooleanClauseOccur());
1309 }
1310 }
1311
1312 postProcessFullQuery(fullBooleanQuery, searchContext);
1313
1314 for (IndexerPostProcessor indexerPostProcessor :
1315 _indexerPostProcessors) {
1316
1317 indexerPostProcessor.postProcessFullQuery(
1318 fullBooleanQuery, searchContext);
1319 }
1320
1321 return fullBooleanQuery;
1322 }
1323
1324 protected Summary createSummary(Document document) {
1325 return createSummary(document, Field.TITLE, Field.CONTENT);
1326 }
1327
1328 protected Summary createSummary(
1329 Document document, String titleField, String contentField) {
1330
1331 String prefix = Field.SNIPPET + StringPool.UNDERLINE;
1332
1333 String title = document.get(prefix + titleField, titleField);
1334 String content = document.get(prefix + contentField, contentField);
1335
1336 return new Summary(title, content);
1337 }
1338
1339 protected void deleteDocument(long companyId, long field1)
1340 throws Exception {
1341
1342 deleteDocument(companyId, String.valueOf(field1));
1343 }
1344
1345 protected void deleteDocument(long companyId, long field1, String field2)
1346 throws Exception {
1347
1348 deleteDocument(companyId, String.valueOf(field1), field2);
1349 }
1350
1351 protected void deleteDocument(long companyId, String field1)
1352 throws Exception {
1353
1354 Document document = new DocumentImpl();
1355
1356 document.addUID(getClassName(), field1);
1357
1358 SearchEngineUtil.deleteDocument(
1359 getSearchEngineId(), companyId, document.get(Field.UID),
1360 _commitImmediately);
1361 }
1362
1363 protected void deleteDocument(long companyId, String field1, String field2)
1364 throws Exception {
1365
1366 Document document = new DocumentImpl();
1367
1368 document.addUID(getClassName(), field1, field2);
1369
1370 SearchEngineUtil.deleteDocument(
1371 getSearchEngineId(), companyId, document.get(Field.UID),
1372 _commitImmediately);
1373 }
1374
1375 protected abstract void doDelete(Object obj) throws Exception;
1376
1377 protected abstract Document doGetDocument(Object obj) throws Exception;
1378
1379 protected String doGetSortField(String orderByCol) {
1380 return orderByCol;
1381 }
1382
1383 protected abstract Summary doGetSummary(
1384 Document document, Locale locale, String snippet,
1385 PortletRequest portletRequest, PortletResponse portletResponse)
1386 throws Exception;
1387
1388
1393 @Deprecated
1394 protected void doPostProcessSearchQuery(
1395 Indexer indexer, BooleanQuery searchQuery,
1396 SearchContext searchContext)
1397 throws Exception {
1398
1399 indexer.postProcessSearchQuery(searchQuery, searchContext);
1400
1401 for (IndexerPostProcessor indexerPostProcessor :
1402 indexer.getIndexerPostProcessors()) {
1403
1404 indexerPostProcessor.postProcessSearchQuery(
1405 searchQuery, searchContext);
1406 }
1407 }
1408
1409 protected abstract void doReindex(Object obj) throws Exception;
1410
1411 protected abstract void doReindex(String className, long classPK)
1412 throws Exception;
1413
1414 protected abstract void doReindex(String[] ids) throws Exception;
1415
1416 protected Hits doSearch(SearchContext searchContext)
1417 throws SearchException {
1418
1419 searchContext.setSearchEngineId(getSearchEngineId());
1420
1421 Query fullQuery = getFullQuery(searchContext);
1422
1423 if (!fullQuery.hasChildren()) {
1424 BooleanFilter preBooleanFilter = fullQuery.getPreBooleanFilter();
1425
1426 fullQuery = new MatchAllQuery();
1427
1428 fullQuery.setPreBooleanFilter(preBooleanFilter);
1429 }
1430
1431 QueryConfig queryConfig = searchContext.getQueryConfig();
1432
1433 fullQuery.setQueryConfig(queryConfig);
1434
1435 return SearchEngineUtil.search(searchContext, fullQuery);
1436 }
1437
1438 protected Document getBaseModelDocument(
1439 String portletId, BaseModel<?> baseModel) {
1440
1441 return getBaseModelDocument(portletId, baseModel, baseModel);
1442 }
1443
1444 protected Document getBaseModelDocument(
1445 String portletId, BaseModel<?> baseModel,
1446 BaseModel<?> workflowedBaseModel) {
1447
1448 Document document = newDocument();
1449
1450 String className = baseModel.getModelClassName();
1451
1452 long classPK = 0;
1453 long resourcePrimKey = 0;
1454
1455 if (baseModel instanceof ResourcedModel) {
1456 ResourcedModel resourcedModel = (ResourcedModel)baseModel;
1457
1458 classPK = resourcedModel.getResourcePrimKey();
1459 resourcePrimKey = resourcedModel.getResourcePrimKey();
1460 }
1461 else {
1462 classPK = (Long)baseModel.getPrimaryKeyObj();
1463 }
1464
1465 DocumentHelper documentHelper = new DocumentHelper(document);
1466
1467 documentHelper.setEntryKey(className, classPK);
1468
1469 document.addUID(className, classPK);
1470
1471 List<AssetCategory> assetCategories =
1472 AssetCategoryLocalServiceUtil.getCategories(className, classPK);
1473
1474 long[] assetCategoryIds = ListUtil.toLongArray(
1475 assetCategories, AssetCategory.CATEGORY_ID_ACCESSOR);
1476
1477 document.addKeyword(Field.ASSET_CATEGORY_IDS, assetCategoryIds);
1478
1479 addSearchAssetCategoryTitles(
1480 document, Field.ASSET_CATEGORY_TITLES, assetCategories);
1481
1482 long classNameId = PortalUtil.getClassNameId(className);
1483
1484 List<AssetTag> assetTags = AssetTagLocalServiceUtil.getTags(
1485 classNameId, classPK);
1486
1487 String[] assetTagNames = ListUtil.toArray(
1488 assetTags, AssetTag.NAME_ACCESSOR);
1489
1490 document.addText(Field.ASSET_TAG_NAMES, assetTagNames);
1491
1492 long[] assetTagsIds = ListUtil.toLongArray(
1493 assetTags, AssetTag.TAG_ID_ACCESSOR);
1494
1495 document.addKeyword(Field.ASSET_TAG_IDS, assetTagsIds);
1496
1497 if (resourcePrimKey > 0) {
1498 document.addKeyword(Field.ROOT_ENTRY_CLASS_PK, resourcePrimKey);
1499 }
1500
1501 if (baseModel instanceof AttachedModel) {
1502 AttachedModel attachedModel = (AttachedModel)baseModel;
1503
1504 documentHelper.setAttachmentOwnerKey(
1505 attachedModel.getClassNameId(), attachedModel.getClassPK());
1506 }
1507
1508 if (baseModel instanceof AuditedModel) {
1509 AuditedModel auditedModel = (AuditedModel)baseModel;
1510
1511 document.addKeyword(Field.COMPANY_ID, auditedModel.getCompanyId());
1512 document.addDate(Field.CREATE_DATE, auditedModel.getCreateDate());
1513 document.addDate(
1514 Field.MODIFIED_DATE, auditedModel.getModifiedDate());
1515 document.addKeyword(Field.USER_ID, auditedModel.getUserId());
1516
1517 String userName = PortalUtil.getUserName(
1518 auditedModel.getUserId(), auditedModel.getUserName());
1519
1520 document.addKeyword(Field.USER_NAME, userName, true);
1521 }
1522
1523 GroupedModel groupedModel = null;
1524
1525 if (baseModel instanceof GroupedModel) {
1526 groupedModel = (GroupedModel)baseModel;
1527
1528 document.addKeyword(
1529 Field.GROUP_ID, getSiteGroupId(groupedModel.getGroupId()));
1530 document.addKeyword(
1531 Field.SCOPE_GROUP_ID, groupedModel.getGroupId());
1532 }
1533
1534 if (workflowedBaseModel instanceof WorkflowedModel) {
1535 WorkflowedModel workflowedModel =
1536 (WorkflowedModel)workflowedBaseModel;
1537
1538 document.addKeyword(Field.STATUS, workflowedModel.getStatus());
1539 }
1540
1541 if ((groupedModel != null) && (baseModel instanceof TrashedModel)) {
1542 TrashedModel trashedModel = (TrashedModel)baseModel;
1543
1544 if (trashedModel.isInTrash()) {
1545 addTrashFields(document, trashedModel);
1546 }
1547 }
1548
1549 addAssetFields(document, className, classPK);
1550
1551 ExpandoBridgeIndexerUtil.addAttributes(
1552 document, baseModel.getExpandoBridge());
1553
1554 return document;
1555 }
1556
1557 protected String getClassName(SearchContext searchContext) {
1558 return getClassName();
1559 }
1560
1561 protected String[] getDefaultSelectedFieldNames() {
1562 return _defaultSelectedFieldNames;
1563 }
1564
1565 protected String[] getDefaultSelectedLocalizedFieldNames() {
1566 return _defaultSelectedLocalizedFieldNames;
1567 }
1568
1569 protected String getExpandoFieldName(
1570 SearchContext searchContext, ExpandoBridge expandoBridge,
1571 String attributeName) {
1572
1573 ExpandoColumn expandoColumn =
1574 ExpandoColumnLocalServiceUtil.getDefaultTableColumn(
1575 expandoBridge.getCompanyId(), expandoBridge.getClassName(),
1576 attributeName);
1577
1578 String fieldName = ExpandoBridgeIndexerUtil.encodeFieldName(
1579 attributeName);
1580
1581 if (expandoColumn.getType() ==
1582 ExpandoColumnConstants.STRING_LOCALIZED) {
1583
1584 fieldName = DocumentImpl.getLocalizedName(
1585 searchContext.getLocale(), fieldName);
1586 }
1587
1588 return fieldName;
1589 }
1590
1591 protected Locale getLocale(PortletRequest portletRequest) {
1592 if (portletRequest != null) {
1593 return portletRequest.getLocale();
1594 }
1595
1596 return LocaleUtil.getMostRelevantLocale();
1597 }
1598
1599 protected Set<String> getLocalizedCountryNames(Country country) {
1600 Set<String> countryNames = new HashSet<>();
1601
1602 for (Locale locale : LanguageUtil.getAvailableLocales()) {
1603 String countryName = country.getName(locale);
1604
1605 countryName = StringUtil.toLowerCase(countryName);
1606
1607 countryNames.add(countryName);
1608 }
1609
1610 return countryNames;
1611 }
1612
1613
1616 @Deprecated
1617 protected String getPortletId(SearchContext searchContext) {
1618 return StringPool.BLANK;
1619 }
1620
1621 protected Group getSiteGroup(long groupId) {
1622 Group group = null;
1623
1624 try {
1625 group = GroupLocalServiceUtil.getGroup(groupId);
1626
1627 if (group.isLayout()) {
1628 group = group.getParentGroup();
1629 }
1630 }
1631 catch (PortalException pe) {
1632 if (_log.isDebugEnabled()) {
1633 _log.debug("Unable to get site group", pe);
1634 }
1635 }
1636
1637 return group;
1638 }
1639
1640 protected long getSiteGroupId(long groupId) {
1641 Group group = getSiteGroup(groupId);
1642
1643 if (group == null) {
1644 return groupId;
1645 }
1646
1647 return group.getGroupId();
1648 }
1649
1650 protected Locale getSnippetLocale(Document document, Locale locale) {
1651 String prefix = Field.SNIPPET + StringPool.UNDERLINE;
1652
1653 String localizedAssetCategoryTitlesName =
1654 prefix +
1655 DocumentImpl.getLocalizedName(locale, Field.ASSET_CATEGORY_TITLES);
1656 String localizedContentName =
1657 prefix + DocumentImpl.getLocalizedName(locale, Field.CONTENT);
1658 String localizedDescriptionName =
1659 prefix + DocumentImpl.getLocalizedName(locale, Field.DESCRIPTION);
1660 String localizedTitleName =
1661 prefix + DocumentImpl.getLocalizedName(locale, Field.TITLE);
1662
1663 if ((document.getField(localizedAssetCategoryTitlesName) != null) ||
1664 (document.getField(localizedContentName) != null) ||
1665 (document.getField(localizedDescriptionName) != null) ||
1666 (document.getField(localizedTitleName) != null)) {
1667
1668 return locale;
1669 }
1670
1671 return null;
1672 }
1673
1674 protected boolean isStagingGroup(long groupId) {
1675 Group group = getSiteGroup(groupId);
1676
1677 if (group == null) {
1678 return false;
1679 }
1680
1681 return group.isStagingGroup();
1682 }
1683
1684 protected boolean isUseSearchResultPermissionFilter(
1685 SearchContext searchContext) {
1686
1687 return isFilterSearch();
1688 }
1689
1690 protected boolean isVisible(int entryStatus, int queryStatus) {
1691 if (((queryStatus != WorkflowConstants.STATUS_ANY) &&
1692 (entryStatus == queryStatus)) ||
1693 (entryStatus != WorkflowConstants.STATUS_IN_TRASH)) {
1694
1695 return true;
1696 }
1697
1698 return false;
1699 }
1700
1701 protected Document newDocument() {
1702 return (Document)_document.clone();
1703 }
1704
1705 protected void populateAddresses(
1706 Document document, List<Address> addresses, long regionId,
1707 long countryId)
1708 throws PortalException {
1709
1710 List<String> cities = new ArrayList<>();
1711
1712 List<String> countries = new ArrayList<>();
1713
1714 if (countryId > 0) {
1715 try {
1716 Country country = CountryServiceUtil.getCountry(countryId);
1717
1718 countries.addAll(getLocalizedCountryNames(country));
1719 }
1720 catch (NoSuchCountryException nsce) {
1721 if (_log.isWarnEnabled()) {
1722 _log.warn(nsce.getMessage());
1723 }
1724 }
1725 }
1726
1727 List<String> regions = new ArrayList<>();
1728
1729 if (regionId > 0) {
1730 try {
1731 Region region = RegionServiceUtil.getRegion(regionId);
1732
1733 regions.add(StringUtil.toLowerCase(region.getName()));
1734 }
1735 catch (NoSuchRegionException nsre) {
1736 if (_log.isWarnEnabled()) {
1737 _log.warn(nsre.getMessage());
1738 }
1739 }
1740 }
1741
1742 List<String> streets = new ArrayList<>();
1743 List<String> zips = new ArrayList<>();
1744
1745 for (Address address : addresses) {
1746 cities.add(StringUtil.toLowerCase(address.getCity()));
1747 countries.addAll(getLocalizedCountryNames(address.getCountry()));
1748 regions.add(StringUtil.toLowerCase(address.getRegion().getName()));
1749 streets.add(StringUtil.toLowerCase(address.getStreet1()));
1750 streets.add(StringUtil.toLowerCase(address.getStreet2()));
1751 streets.add(StringUtil.toLowerCase(address.getStreet3()));
1752 zips.add(StringUtil.toLowerCase(address.getZip()));
1753 }
1754
1755 document.addText("city", cities.toArray(new String[cities.size()]));
1756 document.addText(
1757 "country", countries.toArray(new String[countries.size()]));
1758 document.addText("region", regions.toArray(new String[regions.size()]));
1759 document.addText("street", streets.toArray(new String[streets.size()]));
1760 document.addText("zip", zips.toArray(new String[zips.size()]));
1761 }
1762
1763 protected Map<Locale, String> populateMap(
1764 AssetEntry assetEntry, Map<Locale, String> map) {
1765
1766 String defaultValue = map.get(
1767 LocaleUtil.fromLanguageId(assetEntry.getDefaultLanguageId()));
1768
1769 for (Locale availableLocale : LanguageUtil.getAvailableLocales(
1770 assetEntry.getGroupId())) {
1771
1772 if (!map.containsKey(availableLocale) ||
1773 Validator.isNull(map.get(availableLocale))) {
1774
1775 map.put(availableLocale, defaultValue);
1776 }
1777 }
1778
1779 return map;
1780 }
1781
1782 protected void postProcessFullQuery(
1783 BooleanQuery fullQuery, SearchContext searchContext)
1784 throws Exception {
1785 }
1786
1787 protected void processHits(SearchContext searchContext, Hits hits)
1788 throws SearchException {
1789
1790 HitsProcessor hitsProcessor =
1791 HitsProcessorRegistryUtil.getDefaultHitsProcessor();
1792
1793 if (hitsProcessor != null) {
1794 hitsProcessor.process(searchContext, hits);
1795 }
1796 }
1797
1798 protected void resetFullQuery(SearchContext searchContext) {
1799 searchContext.clearFullQueryEntryClassNames();
1800
1801 for (Indexer indexer : IndexerRegistryUtil.getIndexers()) {
1802 if (indexer instanceof RelatedEntryIndexer) {
1803 RelatedEntryIndexer relatedEntryIndexer =
1804 (RelatedEntryIndexer)indexer;
1805
1806 relatedEntryIndexer.updateFullQuery(searchContext);
1807 }
1808 }
1809 }
1810
1811 protected void setDefaultSelectedFieldNames(
1812 String... defaultLocalizedFieldNames) {
1813
1814 _defaultSelectedFieldNames = defaultLocalizedFieldNames;
1815 }
1816
1817 protected void setDefaultSelectedLocalizedFieldNames(
1818 String... defaultLocalizedFieldNames) {
1819
1820 _defaultSelectedLocalizedFieldNames = defaultLocalizedFieldNames;
1821 }
1822
1823 protected void setFilterSearch(boolean filterSearch) {
1824 _filterSearch = filterSearch;
1825 }
1826
1827 protected void setIndexerEnabled(boolean indexerEnabled) {
1828 _indexerEnabled = indexerEnabled;
1829 }
1830
1831 protected void setPermissionAware(boolean permissionAware) {
1832 _permissionAware = permissionAware;
1833 }
1834
1835 protected void setStagingAware(boolean stagingAware) {
1836 _stagingAware = stagingAware;
1837 }
1838
1839 private static final long _DEFAULT_FOLDER_ID = 0L;
1840
1841 private static final Log _log = LogFactoryUtil.getLog(BaseIndexer.class);
1842
1843 private boolean _commitImmediately;
1844 private String[] _defaultSelectedFieldNames;
1845 private String[] _defaultSelectedLocalizedFieldNames;
1846 private final Document _document = new DocumentImpl();
1847 private boolean _filterSearch;
1848 private boolean _indexerEnabled = true;
1849 private IndexerPostProcessor[] _indexerPostProcessors =
1850 new IndexerPostProcessor[0];
1851 private boolean _permissionAware;
1852 private String _searchEngineId;
1853 private boolean _selectAllLocales;
1854 private boolean _stagingAware = true;
1855
1856 }