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