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