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