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