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