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