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