001
014
015 package com.liferay.portal.kernel.search;
016
017 import com.liferay.portal.exception.NoSuchCountryException;
018 import com.liferay.portal.exception.NoSuchModelException;
019 import com.liferay.portal.exception.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 IndexWriterHelperUtil.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 SearchEngineHelperUtil.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 = SearchEngineHelperUtil.getSearchEngine(
318 searchEngineId);
319
320 if (searchEngine != null) {
321 _searchEngineId = searchEngineId;
322 }
323 }
324
325 if (_searchEngineId == null) {
326 _searchEngineId = SearchEngineHelperUtil.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 (IndexWriterHelperUtil.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 (IndexWriterHelperUtil.isIndexReadOnly() ||
550 !isIndexerEnabled() || (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 (IndexWriterHelperUtil.isIndexReadOnly() ||
574 !isIndexerEnabled()) {
575
576 return;
577 }
578
579 doReindex(ids);
580 }
581 catch (SearchException se) {
582 throw se;
583 }
584 catch (Exception e) {
585 throw new SearchException(e);
586 }
587 }
588
589 @Override
590 public void reindex(T object) throws SearchException {
591 try {
592 if (IndexWriterHelperUtil.isIndexReadOnly() ||
593 !isIndexerEnabled()) {
594
595 return;
596 }
597
598 if (object == null) {
599 return;
600 }
601
602 doReindex(object);
603 }
604 catch (SearchException se) {
605 throw se;
606 }
607 catch (Exception e) {
608 throw new SearchException(e);
609 }
610 }
611
612 @Override
613 public Hits search(SearchContext searchContext) throws SearchException {
614 try {
615 Hits hits = null;
616
617 QueryConfig queryConfig = searchContext.getQueryConfig();
618
619 addDefaultHighlightFieldNames(queryConfig);
620
621 if (ArrayUtil.isEmpty(queryConfig.getSelectedFieldNames())) {
622 addDefaultSelectedFieldNames(searchContext);
623 }
624
625 addFacetSelectedFieldNames(searchContext, queryConfig);
626
627 PermissionChecker permissionChecker =
628 PermissionThreadLocal.getPermissionChecker();
629
630 if ((permissionChecker != null) &&
631 isUseSearchResultPermissionFilter(searchContext)) {
632
633 SearchResultPermissionFilter searchResultPermissionFilter =
634 new DefaultSearchResultPermissionFilter(
635 this, permissionChecker);
636
637 hits = searchResultPermissionFilter.search(searchContext);
638 }
639 else {
640 hits = doSearch(searchContext);
641 }
642
643 processHits(searchContext, hits);
644
645 return hits;
646 }
647 catch (SearchException se) {
648 throw se;
649 }
650 catch (Exception e) {
651 throw new SearchException(e);
652 }
653 }
654
655 @Override
656 public Hits search(
657 SearchContext searchContext, String... selectedFieldNames)
658 throws SearchException {
659
660 QueryConfig queryConfig = searchContext.getQueryConfig();
661
662 queryConfig.setSelectedFieldNames(selectedFieldNames);
663
664 return search(searchContext);
665 }
666
667 @Override
668 public long searchCount(SearchContext searchContext)
669 throws SearchException {
670
671 PermissionChecker permissionChecker =
672 PermissionThreadLocal.getPermissionChecker();
673
674 if ((permissionChecker != null) &&
675 isUseSearchResultPermissionFilter(searchContext)) {
676
677 Hits hits = search(searchContext);
678
679 return hits.getLength();
680 }
681
682 QueryConfig queryConfig = searchContext.getQueryConfig();
683
684 queryConfig.setHighlightEnabled(false);
685 queryConfig.setHitsProcessingEnabled(false);
686 queryConfig.setScoreEnabled(false);
687 queryConfig.setQueryIndexingEnabled(false);
688 queryConfig.setQuerySuggestionEnabled(false);
689
690 searchContext.setSearchEngineId(getSearchEngineId());
691
692 BooleanQuery fullQuery = getFullQuery(searchContext);
693
694 fullQuery.setQueryConfig(queryConfig);
695
696 return IndexSearcherHelperUtil.searchCount(searchContext, fullQuery);
697 }
698
699 public void setCommitImmediately(boolean commitImmediately) {
700 _commitImmediately = commitImmediately;
701 }
702
703 @Override
704 public void setIndexerEnabled(boolean indexerEnabled) {
705 _indexerEnabled = indexerEnabled;
706 }
707
708 public void setSelectAllLocales(boolean selectAllLocales) {
709 _selectAllLocales = selectAllLocales;
710 }
711
712 @Override
713 public void unregisterIndexerPostProcessor(
714 IndexerPostProcessor indexerPostProcessor) {
715
716 List<IndexerPostProcessor> indexerPostProcessorsList =
717 ListUtil.fromArray(_indexerPostProcessors);
718
719 indexerPostProcessorsList.remove(indexerPostProcessor);
720
721 _indexerPostProcessors = indexerPostProcessorsList.toArray(
722 new IndexerPostProcessor[indexerPostProcessorsList.size()]);
723 }
724
725 protected void addAssetFields(
726 Document document, String className, long classPK) {
727
728 AssetRendererFactory<?> assetRendererFactory =
729 AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClassName(
730 className);
731
732 if ((assetRendererFactory == null) ||
733 !assetRendererFactory.isSelectable()) {
734
735 return;
736 }
737
738 AssetEntry assetEntry = AssetEntryLocalServiceUtil.fetchEntry(
739 className, classPK);
740
741 if (assetEntry == null) {
742 return;
743 }
744
745 if (!document.hasField(Field.CREATE_DATE)) {
746 document.addDate(Field.CREATE_DATE, assetEntry.getCreateDate());
747 }
748
749 if (assetEntry.getExpirationDate() != null) {
750 document.addDate(
751 Field.EXPIRATION_DATE, assetEntry.getExpirationDate());
752 }
753 else {
754 document.addDate(Field.EXPIRATION_DATE, new Date(Long.MAX_VALUE));
755 }
756
757 if (!document.hasField(Field.MODIFIED_DATE)) {
758 document.addDate(Field.MODIFIED_DATE, assetEntry.getModifiedDate());
759 }
760
761 document.addNumber(Field.PRIORITY, assetEntry.getPriority());
762
763 if (assetEntry.getPublishDate() != null) {
764 document.addDate(Field.PUBLISH_DATE, assetEntry.getPublishDate());
765 }
766 else {
767 document.addDate(Field.PUBLISH_DATE, new Date(0));
768 }
769
770 RatingsStats ratingsStats = RatingsStatsLocalServiceUtil.fetchStats(
771 className, classPK);
772
773 if (ratingsStats != null) {
774 document.addNumber(Field.RATINGS, ratingsStats.getAverageScore());
775 }
776 else {
777 document.addNumber(Field.RATINGS, 0.0f);
778 }
779
780 document.addNumber(Field.VIEW_COUNT, assetEntry.getViewCount());
781
782 document.addLocalizedKeyword(
783 "localized_title",
784 populateMap(assetEntry, assetEntry.getTitleMap()), true, true);
785 document.addKeyword("visible", assetEntry.isVisible());
786 }
787
788 protected void addDefaultHighlightFieldNames(QueryConfig queryConfig) {
789 queryConfig.addHighlightFieldNames(Field.ASSET_CATEGORY_TITLES);
790
791 if (queryConfig.isHighlightEnabled()) {
792 queryConfig.addHighlightFieldNames(
793 Field.CONTENT, Field.DESCRIPTION, Field.TITLE);
794 }
795 }
796
797 protected void addDefaultSelectedFieldNames(SearchContext searchContext) {
798 QueryConfig queryConfig = searchContext.getQueryConfig();
799
800 Set<String> selectedFieldNames = null;
801
802 if (!ArrayUtil.isEmpty(getDefaultSelectedFieldNames())) {
803 selectedFieldNames = SetUtil.fromArray(
804 getDefaultSelectedFieldNames());
805
806 if (searchContext.isIncludeAttachments() ||
807 searchContext.isIncludeDiscussions()) {
808
809 selectedFieldNames.add(Field.CLASS_NAME_ID);
810 selectedFieldNames.add(Field.CLASS_PK);
811 }
812 }
813
814 if (!ArrayUtil.isEmpty(getDefaultSelectedLocalizedFieldNames())) {
815 if (selectedFieldNames == null) {
816 selectedFieldNames = new HashSet<>();
817 }
818
819 if (isSelectAllLocales()) {
820 addSelectedLocalizedFieldNames(
821 selectedFieldNames,
822 LocaleUtil.toLanguageIds(
823 LanguageUtil.getSupportedLocales()));
824 }
825 else {
826 addSelectedLocalizedFieldNames(
827 selectedFieldNames,
828 LocaleUtil.toLanguageId(queryConfig.getLocale()));
829 }
830 }
831
832 if ((selectedFieldNames != null) && !selectedFieldNames.isEmpty()) {
833 queryConfig.setSelectedFieldNames(
834 selectedFieldNames.toArray(
835 new String[selectedFieldNames.size()]));
836 }
837 }
838
839
842 @Deprecated
843 protected void addFacetClause(
844 SearchContext searchContext, BooleanFilter facetBooleanFilter,
845 Collection<Facet> facets)
846 throws ParseException {
847
848 BooleanQuery facetBooleanQuery = new BooleanQueryImpl();
849
850 for (Facet facet : facets) {
851 BooleanClause<Query> facetBooleanClause = facet.getFacetClause();
852
853 if (facetBooleanClause != null) {
854 facetBooleanQuery.add(
855 facetBooleanClause.getClause(),
856 facetBooleanClause.getBooleanClauseOccur());
857 }
858 }
859
860 if (!facetBooleanQuery.hasClauses()) {
861 return;
862 }
863
864 QueryFilter queryFilter = new QueryFilter(facetBooleanQuery);
865
866 facetBooleanFilter.add(queryFilter, BooleanClauseOccur.MUST);
867 }
868
869 protected void addFacetSelectedFieldNames(
870 SearchContext searchContext, QueryConfig queryConfig) {
871
872 String[] selectedFieldNames = queryConfig.getSelectedFieldNames();
873
874 if (ArrayUtil.isEmpty(selectedFieldNames) ||
875 (selectedFieldNames.length == 1) &&
876 selectedFieldNames[0].equals(Field.ANY)) {
877
878 return;
879 }
880
881 Set<String> selectedFieldNameSet = SetUtil.fromArray(
882 selectedFieldNames);
883
884 Map<String, Facet> facets = searchContext.getFacets();
885
886 selectedFieldNameSet.addAll(facets.keySet());
887
888 selectedFieldNames = selectedFieldNameSet.toArray(
889 new String[selectedFieldNameSet.size()]);
890
891 queryConfig.setSelectedFieldNames(selectedFieldNames);
892 }
893
894 protected void addSearchAssetCategoryIds(
895 BooleanFilter queryBooleanFilter, SearchContext searchContext)
896 throws Exception {
897
898 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
899
900 multiValueFacet.setFieldName(Field.ASSET_CATEGORY_IDS);
901 multiValueFacet.setStatic(true);
902 multiValueFacet.setValues(searchContext.getAssetCategoryIds());
903
904 searchContext.addFacet(multiValueFacet);
905 }
906
907 protected void addSearchAssetCategoryTitles(
908 Document document, String field, List<AssetCategory> assetCategories) {
909
910 Map<Locale, List<String>> assetCategoryTitles = new HashMap<>();
911
912 Locale defaultLocale = LocaleUtil.getDefault();
913
914 for (AssetCategory assetCategory : assetCategories) {
915 Map<Locale, String> titleMap = assetCategory.getTitleMap();
916
917 for (Map.Entry<Locale, String> entry : titleMap.entrySet()) {
918 Locale locale = entry.getKey();
919 String title = entry.getValue();
920
921 if (Validator.isNull(title)) {
922 continue;
923 }
924
925 List<String> titles = assetCategoryTitles.get(locale);
926
927 if (titles == null) {
928 titles = new ArrayList<>();
929
930 assetCategoryTitles.put(locale, titles);
931 }
932
933 titles.add(StringUtil.toLowerCase(title));
934 }
935 }
936
937 for (Map.Entry<Locale, List<String>> entry :
938 assetCategoryTitles.entrySet()) {
939
940 Locale locale = entry.getKey();
941 List<String> titles = entry.getValue();
942
943 String[] titlesArray = titles.toArray(new String[titles.size()]);
944
945 if (locale.equals(defaultLocale)) {
946 document.addText(field, titlesArray);
947 }
948
949 document.addText(
950 field.concat(StringPool.UNDERLINE).concat(locale.toString()),
951 titlesArray);
952 }
953 }
954
955 protected void addSearchAssetTagNames(
956 BooleanFilter queryBooleanFilter, SearchContext searchContext)
957 throws Exception {
958
959 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
960
961 multiValueFacet.setFieldName(Field.ASSET_TAG_NAMES);
962 multiValueFacet.setStatic(true);
963 multiValueFacet.setValues(searchContext.getAssetTagNames());
964
965 searchContext.addFacet(multiValueFacet);
966 }
967
968 protected Filter addSearchClassTypeIds(
969 BooleanFilter contextBooleanFilter, SearchContext searchContext)
970 throws Exception {
971
972 long[] classTypeIds = searchContext.getClassTypeIds();
973
974 if (ArrayUtil.isEmpty(classTypeIds)) {
975 return null;
976 }
977
978 TermsFilter classTypeIdsTermsFilter = new TermsFilter(
979 Field.CLASS_TYPE_ID);
980
981 classTypeIdsTermsFilter.addValues(
982 ArrayUtil.toStringArray(classTypeIds));
983
984 return contextBooleanFilter.add(
985 classTypeIdsTermsFilter, BooleanClauseOccur.MUST);
986 }
987
988 protected void addSearchEntryClassNames(
989 BooleanFilter queryBooleanFilter, SearchContext searchContext)
990 throws Exception {
991
992 Facet facet = new AssetEntriesFacet(searchContext);
993
994 facet.setStatic(true);
995
996 searchContext.addFacet(facet);
997 }
998
999 protected Map<String, Query> addSearchExpando(
1000 BooleanQuery searchQuery, SearchContext searchContext,
1001 String keywords)
1002 throws Exception {
1003
1004 Map<String, Query> expandoQueries = new HashMap<>();
1005
1006 ExpandoBridge expandoBridge = ExpandoBridgeFactoryUtil.getExpandoBridge(
1007 searchContext.getCompanyId(), getClassName(searchContext));
1008
1009 Set<String> attributeNames = SetUtil.fromEnumeration(
1010 expandoBridge.getAttributeNames());
1011
1012 for (String attributeName : attributeNames) {
1013 UnicodeProperties properties = expandoBridge.getAttributeProperties(
1014 attributeName);
1015
1016 int indexType = GetterUtil.getInteger(
1017 properties.getProperty(ExpandoColumnConstants.INDEX_TYPE));
1018
1019 if (indexType != ExpandoColumnConstants.INDEX_TYPE_NONE) {
1020 String fieldName = getExpandoFieldName(
1021 searchContext, expandoBridge, attributeName);
1022
1023 if (Validator.isNotNull(keywords)) {
1024 if (searchContext.isAndSearch()) {
1025 Query query = searchQuery.addRequiredTerm(
1026 fieldName, keywords);
1027
1028 expandoQueries.put(attributeName, query);
1029 }
1030 else {
1031 Query query = searchQuery.addTerm(fieldName, keywords);
1032
1033 expandoQueries.put(attributeName, query);
1034 }
1035 }
1036 }
1037 }
1038
1039 return expandoQueries;
1040 }
1041
1042 protected void addSearchFolderId(
1043 BooleanFilter queryBooleanFilter, SearchContext searchContext)
1044 throws Exception {
1045
1046 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
1047
1048 multiValueFacet.setFieldName(Field.TREE_PATH);
1049 multiValueFacet.setStatic(true);
1050
1051 long[] folderIds = searchContext.getFolderIds();
1052
1053 if (ArrayUtil.isNotEmpty(folderIds)) {
1054 folderIds = ArrayUtil.remove(folderIds, _DEFAULT_FOLDER_ID);
1055
1056 multiValueFacet.setValues(folderIds);
1057 }
1058
1059 searchContext.addFacet(multiValueFacet);
1060 }
1061
1062 protected void addSearchGroupId(
1063 BooleanFilter queryBooleanFilter, SearchContext searchContext)
1064 throws Exception {
1065
1066 Facet facet = new ScopeFacet(searchContext);
1067
1068 facet.setStatic(true);
1069
1070 searchContext.addFacet(facet);
1071 }
1072
1073 protected Map<String, Query> addSearchKeywords(
1074 BooleanQuery searchQuery, SearchContext searchContext)
1075 throws Exception {
1076
1077 String keywords = searchContext.getKeywords();
1078
1079 if (Validator.isNull(keywords)) {
1080 return Collections.emptyMap();
1081 }
1082
1083 addSearchExpando(searchQuery, searchContext, keywords);
1084
1085 addSearchLocalizedTerm(
1086 searchQuery, searchContext, Field.ASSET_CATEGORY_TITLES,
1087 searchContext.isLike());
1088
1089 return searchQuery.addTerms(
1090 Field.KEYWORDS, keywords, searchContext.isLike());
1091 }
1092
1093 protected void addSearchLayout(
1094 BooleanFilter queryBooleanFilter, SearchContext searchContext)
1095 throws Exception {
1096
1097 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
1098
1099 multiValueFacet.setFieldName(Field.LAYOUT_UUID);
1100 multiValueFacet.setStatic(true);
1101
1102 searchContext.addFacet(multiValueFacet);
1103 }
1104
1105 protected Map<String, Query> addSearchLocalizedTerm(
1106 BooleanQuery searchQuery, SearchContext searchContext, String field,
1107 boolean like)
1108 throws Exception {
1109
1110 Map<String, Query> queries = new HashMap<>();
1111
1112 Query query = addSearchTerm(searchQuery, searchContext, field, like);
1113
1114 queries.put(field, query);
1115
1116 String localizedFieldName = DocumentImpl.getLocalizedName(
1117 searchContext.getLocale(), field);
1118
1119 Query localizedQuery = addSearchTerm(
1120 searchQuery, searchContext, localizedFieldName, like);
1121
1122 queries.put(localizedFieldName, localizedQuery);
1123
1124 return queries;
1125 }
1126
1127 protected Query addSearchTerm(
1128 BooleanQuery searchQuery, SearchContext searchContext, String field,
1129 boolean like)
1130 throws Exception {
1131
1132 if (Validator.isNull(field)) {
1133 return null;
1134 }
1135
1136 String value = null;
1137
1138 Serializable serializable = searchContext.getAttribute(field);
1139
1140 if (serializable != null) {
1141 Class<?> clazz = serializable.getClass();
1142
1143 if (clazz.isArray()) {
1144 value = StringUtil.merge((Object[])serializable);
1145 }
1146 else {
1147 value = GetterUtil.getString(serializable);
1148 }
1149 }
1150 else {
1151 value = GetterUtil.getString(serializable);
1152 }
1153
1154 if (Validator.isNotNull(value) &&
1155 (searchContext.getFacet(field) != null)) {
1156
1157 return null;
1158 }
1159
1160 if (Validator.isNull(value)) {
1161 value = searchContext.getKeywords();
1162 }
1163
1164 if (Validator.isNull(value)) {
1165 return null;
1166 }
1167
1168 Query query = null;
1169
1170 if (searchContext.isAndSearch()) {
1171 query = searchQuery.addRequiredTerm(field, value, like);
1172 }
1173 else {
1174 query = searchQuery.addTerm(field, value, like);
1175 }
1176
1177 return query;
1178 }
1179
1180 protected void addSearchUserId(
1181 BooleanFilter queryBooleanFilter, SearchContext searchContext)
1182 throws Exception {
1183
1184 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
1185
1186 multiValueFacet.setFieldName(Field.USER_ID);
1187 multiValueFacet.setStatic(true);
1188
1189 long userId = GetterUtil.getLong(
1190 searchContext.getAttribute(Field.USER_ID));
1191
1192 if (userId > 0) {
1193 multiValueFacet.setValues(new long[] {userId});
1194 }
1195
1196 searchContext.addFacet(multiValueFacet);
1197 }
1198
1199 protected void addSelectedLocalizedFieldNames(
1200 Set<String> selectedFieldNames, String... languageIds) {
1201
1202 for (String defaultLocalizedSelectedFieldName :
1203 getDefaultSelectedLocalizedFieldNames()) {
1204
1205 selectedFieldNames.add(defaultLocalizedSelectedFieldName);
1206
1207 for (String languageId : languageIds) {
1208 String localizedFieldName = LocalizationUtil.getLocalizedName(
1209 defaultLocalizedSelectedFieldName, languageId);
1210
1211 selectedFieldNames.add(localizedFieldName);
1212 }
1213 }
1214 }
1215
1216 protected void addStagingGroupKeyword(Document document, long groupId) {
1217 if (!isStagingAware()) {
1218 return;
1219 }
1220
1221 document.addKeyword(Field.STAGING_GROUP, isStagingGroup(groupId));
1222 }
1223
1224 protected void addStatus(
1225 BooleanFilter contextBooleanFilter, SearchContext searchContext)
1226 throws Exception {
1227
1228 int[] statuses = GetterUtil.getIntegerValues(
1229 searchContext.getAttribute(Field.STATUS), null);
1230
1231 if (ArrayUtil.isEmpty(statuses)) {
1232 int status = GetterUtil.getInteger(
1233 searchContext.getAttribute(Field.STATUS),
1234 WorkflowConstants.STATUS_APPROVED);
1235
1236 statuses = new int[] {status};
1237 }
1238
1239 if (!ArrayUtil.contains(statuses, WorkflowConstants.STATUS_ANY)) {
1240 TermsFilter statusesTermsFilter = new TermsFilter(Field.STATUS);
1241
1242 statusesTermsFilter.addValues(ArrayUtil.toStringArray(statuses));
1243
1244 contextBooleanFilter.add(
1245 statusesTermsFilter, BooleanClauseOccur.MUST);
1246 }
1247 else {
1248 contextBooleanFilter.addTerm(
1249 Field.STATUS, String.valueOf(WorkflowConstants.STATUS_IN_TRASH),
1250 BooleanClauseOccur.MUST_NOT);
1251 }
1252 }
1253
1254 protected void addTrashFields(
1255 Document document, TrashedModel trashedModel) {
1256
1257 TrashEntry trashEntry = null;
1258
1259 try {
1260 trashEntry = trashedModel.getTrashEntry();
1261 }
1262 catch (PortalException pe) {
1263 if (_log.isDebugEnabled()) {
1264 _log.debug("Unable to get trash entry for " + trashedModel);
1265 }
1266 }
1267
1268 if (trashEntry == null) {
1269 document.addDate(Field.REMOVED_DATE, new Date());
1270
1271 ServiceContext serviceContext =
1272 ServiceContextThreadLocal.getServiceContext();
1273
1274 if (serviceContext != null) {
1275 try {
1276 User user = UserLocalServiceUtil.getUser(
1277 serviceContext.getUserId());
1278
1279 document.addKeyword(
1280 Field.REMOVED_BY_USER_NAME, user.getFullName(), true);
1281 }
1282 catch (PortalException pe) {
1283 if (_log.isDebugEnabled()) {
1284 _log.debug(
1285 "Unable to locate user: " +
1286 serviceContext.getUserId(),
1287 pe);
1288 }
1289 }
1290 }
1291 }
1292 else {
1293 document.addDate(Field.REMOVED_DATE, trashEntry.getCreateDate());
1294 document.addKeyword(
1295 Field.REMOVED_BY_USER_NAME, trashEntry.getUserName(), true);
1296
1297 if (trashedModel.isInTrash() &&
1298 !trashedModel.isInTrashExplicitly()) {
1299
1300 document.addKeyword(
1301 Field.ROOT_ENTRY_CLASS_NAME, trashEntry.getClassName());
1302 document.addKeyword(
1303 Field.ROOT_ENTRY_CLASS_PK, trashEntry.getClassPK());
1304 }
1305 }
1306
1307 TrashHandler trashHandler = trashedModel.getTrashHandler();
1308
1309 try {
1310 TrashRenderer trashRenderer = null;
1311
1312 if ((trashHandler != null) && (trashEntry != null)) {
1313 trashRenderer = trashHandler.getTrashRenderer(
1314 trashEntry.getClassPK());
1315 }
1316
1317 if (trashRenderer != null) {
1318 document.addKeyword(Field.TYPE, trashRenderer.getType(), true);
1319 }
1320 }
1321 catch (PortalException pe) {
1322 if (_log.isDebugEnabled()) {
1323 _log.debug(
1324 "Unable to get trash renderer for " +
1325 trashEntry.getClassName());
1326 }
1327 }
1328 }
1329
1330 protected BooleanQuery createFullQuery(
1331 BooleanFilter fullQueryBooleanFilter, SearchContext searchContext)
1332 throws Exception {
1333
1334 BooleanQuery searchQuery = new BooleanQueryImpl();
1335
1336 addSearchKeywords(searchQuery, searchContext);
1337 postProcessSearchQuery(
1338 searchQuery, fullQueryBooleanFilter, searchContext);
1339
1340 for (IndexerPostProcessor indexerPostProcessor :
1341 _indexerPostProcessors) {
1342
1343 indexerPostProcessor.postProcessSearchQuery(
1344 searchQuery, fullQueryBooleanFilter, searchContext);
1345 }
1346
1347 doPostProcessSearchQuery(this, searchQuery, searchContext);
1348
1349 Map<String, Facet> facets = searchContext.getFacets();
1350
1351 BooleanFilter facetBooleanFilter = new BooleanFilter();
1352
1353 for (Facet facet : facets.values()) {
1354 BooleanClause<Filter> filterBooleanClause =
1355 facet.getFacetFilterBooleanClause();
1356
1357 if (filterBooleanClause != null) {
1358 facetBooleanFilter.add(
1359 filterBooleanClause.getClause(),
1360 filterBooleanClause.getBooleanClauseOccur());
1361 }
1362 }
1363
1364 addFacetClause(searchContext, facetBooleanFilter, facets.values());
1365
1366 if (facetBooleanFilter.hasClauses()) {
1367 fullQueryBooleanFilter.add(
1368 facetBooleanFilter, BooleanClauseOccur.MUST);
1369 }
1370
1371 BooleanQuery fullBooleanQuery = new BooleanQueryImpl();
1372
1373 if (fullQueryBooleanFilter.hasClauses()) {
1374 fullBooleanQuery.setPreBooleanFilter(fullQueryBooleanFilter);
1375 }
1376
1377 if (searchQuery.hasClauses()) {
1378 fullBooleanQuery.add(searchQuery, BooleanClauseOccur.MUST);
1379 }
1380
1381 BooleanClause<Query>[] booleanClauses =
1382 searchContext.getBooleanClauses();
1383
1384 if (booleanClauses != null) {
1385 for (BooleanClause<Query> booleanClause : booleanClauses) {
1386 fullBooleanQuery.add(
1387 booleanClause.getClause(),
1388 booleanClause.getBooleanClauseOccur());
1389 }
1390 }
1391
1392 postProcessFullQuery(fullBooleanQuery, searchContext);
1393
1394 for (IndexerPostProcessor indexerPostProcessor :
1395 _indexerPostProcessors) {
1396
1397 indexerPostProcessor.postProcessFullQuery(
1398 fullBooleanQuery, searchContext);
1399 }
1400
1401 return fullBooleanQuery;
1402 }
1403
1404 protected Summary createSummary(Document document) {
1405 return createSummary(document, Field.TITLE, Field.CONTENT);
1406 }
1407
1408 protected Summary createSummary(
1409 Document document, String titleField, String contentField) {
1410
1411 String prefix = Field.SNIPPET + StringPool.UNDERLINE;
1412
1413 String title = document.get(prefix + titleField, titleField);
1414 String content = document.get(prefix + contentField, contentField);
1415
1416 return new Summary(title, content);
1417 }
1418
1419 protected void deleteDocument(long companyId, long field1)
1420 throws Exception {
1421
1422 deleteDocument(companyId, String.valueOf(field1));
1423 }
1424
1425 protected void deleteDocument(long companyId, long field1, String field2)
1426 throws Exception {
1427
1428 deleteDocument(companyId, String.valueOf(field1), field2);
1429 }
1430
1431 protected void deleteDocument(long companyId, String field1)
1432 throws Exception {
1433
1434 Document document = new DocumentImpl();
1435
1436 document.addUID(getClassName(), field1);
1437
1438 IndexWriterHelperUtil.deleteDocument(
1439 getSearchEngineId(), companyId, document.get(Field.UID),
1440 _commitImmediately);
1441 }
1442
1443 protected void deleteDocument(long companyId, String field1, String field2)
1444 throws Exception {
1445
1446 Document document = new DocumentImpl();
1447
1448 document.addUID(getClassName(), field1, field2);
1449
1450 IndexWriterHelperUtil.deleteDocument(
1451 getSearchEngineId(), companyId, document.get(Field.UID),
1452 _commitImmediately);
1453 }
1454
1455 protected abstract void doDelete(T object) throws Exception;
1456
1457 protected abstract Document doGetDocument(T object) throws Exception;
1458
1459 protected String doGetSortField(String orderByCol) {
1460 return orderByCol;
1461 }
1462
1463 protected abstract Summary doGetSummary(
1464 Document document, Locale locale, String snippet,
1465 PortletRequest portletRequest, PortletResponse portletResponse)
1466 throws Exception;
1467
1468
1473 @Deprecated
1474 protected void doPostProcessSearchQuery(
1475 Indexer<?> indexer, BooleanQuery searchQuery,
1476 SearchContext searchContext)
1477 throws Exception {
1478
1479 indexer.postProcessSearchQuery(searchQuery, searchContext);
1480
1481 for (IndexerPostProcessor indexerPostProcessor :
1482 indexer.getIndexerPostProcessors()) {
1483
1484 indexerPostProcessor.postProcessSearchQuery(
1485 searchQuery, searchContext);
1486 }
1487 }
1488
1489 protected abstract void doReindex(String className, long classPK)
1490 throws Exception;
1491
1492 protected abstract void doReindex(String[] ids) throws Exception;
1493
1494 protected abstract void doReindex(T object) throws Exception;
1495
1496 protected Hits doSearch(SearchContext searchContext)
1497 throws SearchException {
1498
1499 searchContext.setSearchEngineId(getSearchEngineId());
1500
1501 Query fullQuery = getFullQuery(searchContext);
1502
1503 if (!fullQuery.hasChildren()) {
1504 BooleanFilter preBooleanFilter = fullQuery.getPreBooleanFilter();
1505
1506 fullQuery = new MatchAllQuery();
1507
1508 fullQuery.setPreBooleanFilter(preBooleanFilter);
1509 }
1510
1511 QueryConfig queryConfig = searchContext.getQueryConfig();
1512
1513 fullQuery.setQueryConfig(queryConfig);
1514
1515 return IndexSearcherHelperUtil.search(searchContext, fullQuery);
1516 }
1517
1518 protected Document getBaseModelDocument(
1519 String portletId, BaseModel<?> baseModel) {
1520
1521 return getBaseModelDocument(portletId, baseModel, baseModel);
1522 }
1523
1524 protected Document getBaseModelDocument(
1525 String portletId, BaseModel<?> baseModel,
1526 BaseModel<?> workflowedBaseModel) {
1527
1528 Document document = newDocument();
1529
1530 String className = baseModel.getModelClassName();
1531
1532 long classPK = 0;
1533 long resourcePrimKey = 0;
1534
1535 if (baseModel instanceof ResourcedModel) {
1536 ResourcedModel resourcedModel = (ResourcedModel)baseModel;
1537
1538 classPK = resourcedModel.getResourcePrimKey();
1539 resourcePrimKey = resourcedModel.getResourcePrimKey();
1540 }
1541 else {
1542 classPK = (Long)baseModel.getPrimaryKeyObj();
1543 }
1544
1545 DocumentHelper documentHelper = new DocumentHelper(document);
1546
1547 documentHelper.setEntryKey(className, classPK);
1548
1549 document.addUID(className, classPK);
1550
1551 List<AssetCategory> assetCategories =
1552 AssetCategoryLocalServiceUtil.getCategories(className, classPK);
1553
1554 long[] assetCategoryIds = ListUtil.toLongArray(
1555 assetCategories, AssetCategory.CATEGORY_ID_ACCESSOR);
1556
1557 document.addKeyword(Field.ASSET_CATEGORY_IDS, assetCategoryIds);
1558
1559 addSearchAssetCategoryTitles(
1560 document, Field.ASSET_CATEGORY_TITLES, assetCategories);
1561
1562 long classNameId = PortalUtil.getClassNameId(className);
1563
1564 List<AssetTag> assetTags = AssetTagLocalServiceUtil.getTags(
1565 classNameId, classPK);
1566
1567 String[] assetTagNames = ListUtil.toArray(
1568 assetTags, AssetTag.NAME_ACCESSOR);
1569
1570 document.addText(Field.ASSET_TAG_NAMES, assetTagNames);
1571
1572 long[] assetTagsIds = ListUtil.toLongArray(
1573 assetTags, AssetTag.TAG_ID_ACCESSOR);
1574
1575 document.addKeyword(Field.ASSET_TAG_IDS, assetTagsIds);
1576
1577 if (resourcePrimKey > 0) {
1578 document.addKeyword(Field.ROOT_ENTRY_CLASS_PK, resourcePrimKey);
1579 }
1580
1581 if (baseModel instanceof AttachedModel) {
1582 AttachedModel attachedModel = (AttachedModel)baseModel;
1583
1584 documentHelper.setAttachmentOwnerKey(
1585 attachedModel.getClassNameId(), attachedModel.getClassPK());
1586 }
1587
1588 if (baseModel instanceof AuditedModel) {
1589 AuditedModel auditedModel = (AuditedModel)baseModel;
1590
1591 document.addKeyword(Field.COMPANY_ID, auditedModel.getCompanyId());
1592 document.addDate(Field.CREATE_DATE, auditedModel.getCreateDate());
1593 document.addDate(
1594 Field.MODIFIED_DATE, auditedModel.getModifiedDate());
1595 document.addKeyword(Field.USER_ID, auditedModel.getUserId());
1596
1597 String userName = PortalUtil.getUserName(
1598 auditedModel.getUserId(), auditedModel.getUserName());
1599
1600 document.addKeyword(Field.USER_NAME, userName, true);
1601 }
1602
1603 GroupedModel groupedModel = null;
1604
1605 if (baseModel instanceof GroupedModel) {
1606 groupedModel = (GroupedModel)baseModel;
1607
1608 document.addKeyword(
1609 Field.GROUP_ID, getSiteGroupId(groupedModel.getGroupId()));
1610 document.addKeyword(
1611 Field.SCOPE_GROUP_ID, groupedModel.getGroupId());
1612 }
1613
1614 if (workflowedBaseModel instanceof WorkflowedModel) {
1615 WorkflowedModel workflowedModel =
1616 (WorkflowedModel)workflowedBaseModel;
1617
1618 document.addKeyword(Field.STATUS, workflowedModel.getStatus());
1619 }
1620
1621 if ((groupedModel != null) && (baseModel instanceof TrashedModel)) {
1622 TrashedModel trashedModel = (TrashedModel)baseModel;
1623
1624 if (trashedModel.isInTrash()) {
1625 addTrashFields(document, trashedModel);
1626 }
1627 }
1628
1629 addAssetFields(document, className, classPK);
1630
1631 ExpandoBridgeIndexerUtil.addAttributes(
1632 document, baseModel.getExpandoBridge());
1633
1634 return document;
1635 }
1636
1637 protected String getClassName(SearchContext searchContext) {
1638 return getClassName();
1639 }
1640
1641 protected String[] getDefaultSelectedFieldNames() {
1642 return _defaultSelectedFieldNames;
1643 }
1644
1645 protected String[] getDefaultSelectedLocalizedFieldNames() {
1646 return _defaultSelectedLocalizedFieldNames;
1647 }
1648
1649 protected String getExpandoFieldName(
1650 SearchContext searchContext, ExpandoBridge expandoBridge,
1651 String attributeName) {
1652
1653 ExpandoColumn expandoColumn =
1654 ExpandoColumnLocalServiceUtil.getDefaultTableColumn(
1655 expandoBridge.getCompanyId(), expandoBridge.getClassName(),
1656 attributeName);
1657
1658 String fieldName = ExpandoBridgeIndexerUtil.encodeFieldName(
1659 attributeName);
1660
1661 if (expandoColumn.getType() ==
1662 ExpandoColumnConstants.STRING_LOCALIZED) {
1663
1664 fieldName = DocumentImpl.getLocalizedName(
1665 searchContext.getLocale(), fieldName);
1666 }
1667
1668 return fieldName;
1669 }
1670
1671 protected Locale getLocale(PortletRequest portletRequest) {
1672 if (portletRequest != null) {
1673 return portletRequest.getLocale();
1674 }
1675
1676 return LocaleUtil.getMostRelevantLocale();
1677 }
1678
1679 protected Set<String> getLocalizedCountryNames(Country country) {
1680 Set<String> countryNames = new HashSet<>();
1681
1682 for (Locale locale : LanguageUtil.getAvailableLocales()) {
1683 String countryName = country.getName(locale);
1684
1685 countryName = StringUtil.toLowerCase(countryName);
1686
1687 countryNames.add(countryName);
1688 }
1689
1690 return countryNames;
1691 }
1692
1693
1696 @Deprecated
1697 protected String getPortletId(SearchContext searchContext) {
1698 return StringPool.BLANK;
1699 }
1700
1701 protected Group getSiteGroup(long groupId) {
1702 Group group = null;
1703
1704 try {
1705 group = GroupLocalServiceUtil.getGroup(groupId);
1706
1707 if (group.isLayout()) {
1708 group = group.getParentGroup();
1709 }
1710 }
1711 catch (PortalException pe) {
1712 if (_log.isDebugEnabled()) {
1713 _log.debug("Unable to get site group", pe);
1714 }
1715 }
1716
1717 return group;
1718 }
1719
1720 protected long getSiteGroupId(long groupId) {
1721 Group group = getSiteGroup(groupId);
1722
1723 if (group == null) {
1724 return groupId;
1725 }
1726
1727 return group.getGroupId();
1728 }
1729
1730 protected Locale getSnippetLocale(Document document, Locale locale) {
1731 String prefix = Field.SNIPPET + StringPool.UNDERLINE;
1732
1733 String localizedAssetCategoryTitlesName =
1734 prefix +
1735 DocumentImpl.getLocalizedName(
1736 locale, Field.ASSET_CATEGORY_TITLES);
1737 String localizedContentName =
1738 prefix + DocumentImpl.getLocalizedName(locale, Field.CONTENT);
1739 String localizedDescriptionName =
1740 prefix + DocumentImpl.getLocalizedName(locale, Field.DESCRIPTION);
1741 String localizedTitleName =
1742 prefix + DocumentImpl.getLocalizedName(locale, Field.TITLE);
1743
1744 if ((document.getField(localizedAssetCategoryTitlesName) != null) ||
1745 (document.getField(localizedContentName) != null) ||
1746 (document.getField(localizedDescriptionName) != null) ||
1747 (document.getField(localizedTitleName) != null)) {
1748
1749 return locale;
1750 }
1751
1752 return null;
1753 }
1754
1755 protected boolean isStagingGroup(long groupId) {
1756 Group group = getSiteGroup(groupId);
1757
1758 if (group == null) {
1759 return false;
1760 }
1761
1762 return group.isStagingGroup();
1763 }
1764
1765 protected boolean isUseSearchResultPermissionFilter(
1766 SearchContext searchContext) {
1767
1768 return isFilterSearch();
1769 }
1770
1771 protected boolean isVisible(int entryStatus, int queryStatus) {
1772 if (((queryStatus != WorkflowConstants.STATUS_ANY) &&
1773 (entryStatus == queryStatus)) ||
1774 (entryStatus != WorkflowConstants.STATUS_IN_TRASH)) {
1775
1776 return true;
1777 }
1778
1779 return false;
1780 }
1781
1782 protected Document newDocument() {
1783 return (Document)_document.clone();
1784 }
1785
1786 protected void populateAddresses(
1787 Document document, List<Address> addresses, long regionId,
1788 long countryId)
1789 throws PortalException {
1790
1791 List<String> cities = new ArrayList<>();
1792
1793 List<String> countries = new ArrayList<>();
1794
1795 if (countryId > 0) {
1796 try {
1797 Country country = CountryServiceUtil.getCountry(countryId);
1798
1799 countries.addAll(getLocalizedCountryNames(country));
1800 }
1801 catch (NoSuchCountryException nsce) {
1802 if (_log.isWarnEnabled()) {
1803 _log.warn(nsce.getMessage());
1804 }
1805 }
1806 }
1807
1808 List<String> regions = new ArrayList<>();
1809
1810 if (regionId > 0) {
1811 try {
1812 Region region = RegionServiceUtil.getRegion(regionId);
1813
1814 regions.add(StringUtil.toLowerCase(region.getName()));
1815 }
1816 catch (NoSuchRegionException nsre) {
1817 if (_log.isWarnEnabled()) {
1818 _log.warn(nsre.getMessage());
1819 }
1820 }
1821 }
1822
1823 List<String> streets = new ArrayList<>();
1824 List<String> zips = new ArrayList<>();
1825
1826 for (Address address : addresses) {
1827 cities.add(StringUtil.toLowerCase(address.getCity()));
1828 countries.addAll(getLocalizedCountryNames(address.getCountry()));
1829 regions.add(StringUtil.toLowerCase(address.getRegion().getName()));
1830 streets.add(StringUtil.toLowerCase(address.getStreet1()));
1831 streets.add(StringUtil.toLowerCase(address.getStreet2()));
1832 streets.add(StringUtil.toLowerCase(address.getStreet3()));
1833 zips.add(StringUtil.toLowerCase(address.getZip()));
1834 }
1835
1836 document.addText("city", cities.toArray(new String[cities.size()]));
1837 document.addText(
1838 "country", countries.toArray(new String[countries.size()]));
1839 document.addText("region", regions.toArray(new String[regions.size()]));
1840 document.addText("street", streets.toArray(new String[streets.size()]));
1841 document.addText("zip", zips.toArray(new String[zips.size()]));
1842 }
1843
1844 protected Map<Locale, String> populateMap(
1845 AssetEntry assetEntry, Map<Locale, String> map) {
1846
1847 String defaultValue = map.get(
1848 LocaleUtil.fromLanguageId(assetEntry.getDefaultLanguageId()));
1849
1850 for (Locale availableLocale : LanguageUtil.getAvailableLocales(
1851 assetEntry.getGroupId())) {
1852
1853 if (!map.containsKey(availableLocale) ||
1854 Validator.isNull(map.get(availableLocale))) {
1855
1856 map.put(availableLocale, defaultValue);
1857 }
1858 }
1859
1860 return map;
1861 }
1862
1863 protected void postProcessFullQuery(
1864 BooleanQuery fullQuery, SearchContext searchContext)
1865 throws Exception {
1866 }
1867
1868 protected void processHits(SearchContext searchContext, Hits hits)
1869 throws SearchException {
1870
1871 HitsProcessorRegistryUtil.process(searchContext, hits);
1872 }
1873
1874 protected void resetFullQuery(SearchContext searchContext) {
1875 searchContext.clearFullQueryEntryClassNames();
1876
1877 for (Indexer<?> indexer : IndexerRegistryUtil.getIndexers()) {
1878 if (indexer instanceof RelatedEntryIndexer) {
1879 RelatedEntryIndexer relatedEntryIndexer =
1880 (RelatedEntryIndexer)indexer;
1881
1882 relatedEntryIndexer.updateFullQuery(searchContext);
1883 }
1884 }
1885 }
1886
1887 protected void setDefaultSelectedFieldNames(
1888 String... defaultLocalizedFieldNames) {
1889
1890 _defaultSelectedFieldNames = defaultLocalizedFieldNames;
1891 }
1892
1893 protected void setDefaultSelectedLocalizedFieldNames(
1894 String... defaultLocalizedFieldNames) {
1895
1896 _defaultSelectedLocalizedFieldNames = defaultLocalizedFieldNames;
1897 }
1898
1899 protected void setFilterSearch(boolean filterSearch) {
1900 _filterSearch = filterSearch;
1901 }
1902
1903 protected void setPermissionAware(boolean permissionAware) {
1904 _permissionAware = permissionAware;
1905 }
1906
1907 protected void setStagingAware(boolean stagingAware) {
1908 _stagingAware = stagingAware;
1909 }
1910
1911 private static final long _DEFAULT_FOLDER_ID = 0L;
1912
1913 private static final Log _log = LogFactoryUtil.getLog(BaseIndexer.class);
1914
1915 private boolean _commitImmediately;
1916 private String[] _defaultSelectedFieldNames;
1917 private String[] _defaultSelectedLocalizedFieldNames;
1918 private final Document _document = new DocumentImpl();
1919 private boolean _filterSearch;
1920 private Boolean _indexerEnabled;
1921 private IndexerPostProcessor[] _indexerPostProcessors =
1922 new IndexerPostProcessor[0];
1923 private boolean _permissionAware;
1924 private String _searchEngineId;
1925 private boolean _selectAllLocales;
1926 private boolean _stagingAware = true;
1927
1928 }