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