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