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.log.Log;
025 import com.liferay.portal.kernel.log.LogFactoryUtil;
026 import com.liferay.portal.kernel.search.facet.AssetEntriesFacet;
027 import com.liferay.portal.kernel.search.facet.Facet;
028 import com.liferay.portal.kernel.search.facet.MultiValueFacet;
029 import com.liferay.portal.kernel.search.facet.ScopeFacet;
030 import com.liferay.portal.kernel.util.GetterUtil;
031 import com.liferay.portal.kernel.util.ListUtil;
032 import com.liferay.portal.kernel.util.LocaleUtil;
033 import com.liferay.portal.kernel.util.PropsKeys;
034 import com.liferay.portal.kernel.util.PropsUtil;
035 import com.liferay.portal.kernel.util.SetUtil;
036 import com.liferay.portal.kernel.util.StringPool;
037 import com.liferay.portal.kernel.util.StringUtil;
038 import com.liferay.portal.kernel.util.Time;
039 import com.liferay.portal.kernel.util.UnicodeProperties;
040 import com.liferay.portal.kernel.util.Validator;
041 import com.liferay.portal.model.Address;
042 import com.liferay.portal.model.AttachedModel;
043 import com.liferay.portal.model.AuditedModel;
044 import com.liferay.portal.model.BaseModel;
045 import com.liferay.portal.model.Country;
046 import com.liferay.portal.model.Group;
047 import com.liferay.portal.model.GroupedModel;
048 import com.liferay.portal.model.Region;
049 import com.liferay.portal.model.ResourcedModel;
050 import com.liferay.portal.model.WorkflowedModel;
051 import com.liferay.portal.security.permission.ActionKeys;
052 import com.liferay.portal.security.permission.PermissionChecker;
053 import com.liferay.portal.security.permission.PermissionThreadLocal;
054 import com.liferay.portal.service.CountryServiceUtil;
055 import com.liferay.portal.service.GroupLocalServiceUtil;
056 import com.liferay.portal.service.RegionServiceUtil;
057 import com.liferay.portal.util.PortalUtil;
058 import com.liferay.portlet.asset.model.AssetCategory;
059 import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
060 import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
061 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
062 import com.liferay.portlet.dynamicdatamapping.util.DDMIndexerUtil;
063 import com.liferay.portlet.expando.model.ExpandoBridge;
064 import com.liferay.portlet.expando.model.ExpandoColumnConstants;
065 import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
066 import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
067
068 import java.util.ArrayList;
069 import java.util.HashMap;
070 import java.util.List;
071 import java.util.Locale;
072 import java.util.Map;
073 import java.util.Set;
074
075 import javax.portlet.PortletURL;
076
077
083 public abstract class BaseIndexer implements Indexer {
084
085 public static final int INDEX_FILTER_SEARCH_LIMIT = GetterUtil.getInteger(
086 PropsUtil.get(PropsKeys.INDEX_FILTER_SEARCH_LIMIT));
087
088 public void delete(long companyId, String uid) throws SearchException {
089 try {
090 SearchEngineUtil.deleteDocument(
091 getSearchEngineId(), companyId, uid);
092 }
093 catch (SearchException se) {
094 throw se;
095 }
096 catch (Exception e) {
097 throw new SearchException(e);
098 }
099 }
100
101 public void delete(Object obj) throws SearchException {
102 try {
103 doDelete(obj);
104 }
105 catch (SearchException se) {
106 throw se;
107 }
108 catch (Exception e) {
109 throw new SearchException(e);
110 }
111 }
112
113 public Document getDocument(Object obj) throws SearchException {
114 try {
115 Document document = doGetDocument(obj);
116
117 for (IndexerPostProcessor indexerPostProcessor :
118 _indexerPostProcessors) {
119
120 indexerPostProcessor.postProcessDocument(document, obj);
121 }
122
123 if (document == null) {
124 return null;
125 }
126
127 Map<String, Field> fields = document.getFields();
128
129 Field groupIdField = fields.get(Field.GROUP_ID);
130
131 if (groupIdField != null) {
132 long groupId = GetterUtil.getLong(groupIdField.getValue());
133
134 addStagingGroupKeyword(document, groupId);
135 }
136
137 return document;
138 }
139 catch (SearchException se) {
140 throw se;
141 }
142 catch (Exception e) {
143 throw new SearchException(e);
144 }
145 }
146
147 public BooleanQuery getFacetQuery(
148 String className, SearchContext searchContext)
149 throws Exception {
150
151 BooleanQuery facetQuery = BooleanQueryFactoryUtil.create(searchContext);
152
153 facetQuery.addExactTerm(Field.ENTRY_CLASS_NAME, className);
154
155 if (searchContext.getUserId() > 0) {
156 SearchPermissionChecker searchPermissionChecker =
157 SearchEngineUtil.getSearchPermissionChecker();
158
159 facetQuery =
160 (BooleanQuery)searchPermissionChecker.getPermissionQuery(
161 searchContext.getCompanyId(), searchContext.getGroupIds(),
162 searchContext.getUserId(), className, facetQuery,
163 searchContext);
164 }
165
166 return facetQuery;
167 }
168
169 public BooleanQuery getFullQuery(SearchContext searchContext)
170 throws SearchException {
171
172 try {
173 searchContext.setSearchEngineId(getSearchEngineId());
174
175 searchContext.setEntryClassNames(
176 new String[] {getClassName(searchContext)});
177
178 BooleanQuery contextQuery = BooleanQueryFactoryUtil.create(
179 searchContext);
180
181 addSearchAssetCategoryIds(contextQuery, searchContext);
182 addSearchAssetTagNames(contextQuery, searchContext);
183 addSearchEntryClassNames(contextQuery, searchContext);
184 addSearchGroupId(contextQuery, searchContext);
185
186 BooleanQuery fullQuery = createFullQuery(
187 contextQuery, searchContext);
188
189 fullQuery.setQueryConfig(searchContext.getQueryConfig());
190
191 return fullQuery;
192 }
193 catch (SearchException se) {
194 throw se;
195 }
196 catch (Exception e) {
197 throw new SearchException(e);
198 }
199 }
200
201 public IndexerPostProcessor[] getIndexerPostProcessors() {
202 return _indexerPostProcessors;
203 }
204
205 public String getSearchEngineId() {
206 if (_searchEngineId != null) {
207 return _searchEngineId;
208 }
209
210 Class<?> clazz = getClass();
211
212 String searchEngineId = GetterUtil.getString(
213 PropsUtil.get(
214 PropsKeys.INDEX_SEARCH_ENGINE_ID, new Filter(clazz.getName())));
215
216 if (Validator.isNotNull(searchEngineId)) {
217 SearchEngine searchEngine = SearchEngineUtil.getSearchEngine(
218 searchEngineId);
219
220 if (searchEngine != null) {
221 _searchEngineId = searchEngineId;
222 }
223 }
224
225 if (_searchEngineId == null) {
226 _searchEngineId = SearchEngineUtil.getDefaultSearchEngineId();
227 }
228
229 if (_log.isDebugEnabled()) {
230 _log.debug(
231 "Search engine ID for " + clazz.getName() + " is " +
232 searchEngineId);
233 }
234
235 return _searchEngineId;
236 }
237
238 public String getSortField(String orderByCol) {
239 String sortField = doGetSortField(orderByCol);
240
241 if (DocumentImpl.isSortableTextField(sortField)) {
242 return DocumentImpl.getSortableFieldName(sortField);
243 }
244
245 return sortField;
246 }
247
248 public Summary getSummary(
249 Document document, Locale locale, String snippet,
250 PortletURL portletURL)
251 throws SearchException {
252
253 try {
254 Summary summary = doGetSummary(
255 document, locale, snippet, portletURL);
256
257 for (IndexerPostProcessor indexerPostProcessor :
258 _indexerPostProcessors) {
259
260 indexerPostProcessor.postProcessSummary(
261 summary, document, locale, snippet, portletURL);
262 }
263
264 return summary;
265 }
266 catch (SearchException se) {
267 throw se;
268 }
269 catch (Exception e) {
270 throw new SearchException(e);
271 }
272 }
273
274 public boolean hasPermission(
275 PermissionChecker permissionChecker, long entryClassPK,
276 String actionId)
277 throws Exception {
278
279 return true;
280 }
281
282 public boolean isFilterSearch() {
283 return _FILTER_SEARCH;
284 }
285
286 public boolean isIndexerEnabled() {
287 return _INDEXER_ENABLED;
288 }
289
290 public boolean isPermissionAware() {
291 return _PERMISSION_AWARE;
292 }
293
294 public boolean isStagingAware() {
295 return _stagingAware;
296 }
297
298 public void postProcessContextQuery(
299 BooleanQuery contextQuery, SearchContext searchContext)
300 throws Exception {
301 }
302
303 public void postProcessSearchQuery(
304 BooleanQuery searchQuery, SearchContext searchContext)
305 throws Exception {
306 }
307
308 public void registerIndexerPostProcessor(
309 IndexerPostProcessor indexerPostProcessor) {
310
311 List<IndexerPostProcessor> indexerPostProcessorsList =
312 ListUtil.fromArray(_indexerPostProcessors);
313
314 indexerPostProcessorsList.add(indexerPostProcessor);
315
316 _indexerPostProcessors = indexerPostProcessorsList.toArray(
317 new IndexerPostProcessor[indexerPostProcessorsList.size()]);
318 }
319
320 public void reindex(Object obj) throws SearchException {
321 try {
322 if (SearchEngineUtil.isIndexReadOnly() || !isIndexerEnabled()) {
323 return;
324 }
325
326 doReindex(obj);
327 }
328 catch (SearchException se) {
329 throw se;
330 }
331 catch (Exception e) {
332 throw new SearchException(e);
333 }
334 }
335
336 public void reindex(String className, long classPK) throws SearchException {
337 try {
338 if (SearchEngineUtil.isIndexReadOnly() || !isIndexerEnabled()) {
339 return;
340 }
341
342 doReindex(className, classPK);
343 }
344 catch (NoSuchModelException nsme) {
345 if (_log.isWarnEnabled()) {
346 _log.warn("Unable to index " + className + " " + classPK);
347 }
348 }
349 catch (SearchException se) {
350 throw se;
351 }
352 catch (Exception e) {
353 throw new SearchException(e);
354 }
355 }
356
357 public void reindex(String[] ids) throws SearchException {
358 try {
359 if (SearchEngineUtil.isIndexReadOnly() || !isIndexerEnabled()) {
360 return;
361 }
362
363 doReindex(ids);
364 }
365 catch (SearchException se) {
366 throw se;
367 }
368 catch (Exception e) {
369 throw new SearchException(e);
370 }
371 }
372
373 public Hits search(SearchContext searchContext) throws SearchException {
374 try {
375 searchContext.setSearchEngineId(getSearchEngineId());
376
377 BooleanQuery fullQuery = getFullQuery(searchContext);
378
379 fullQuery.setQueryConfig(searchContext.getQueryConfig());
380
381 PermissionChecker permissionChecker =
382 PermissionThreadLocal.getPermissionChecker();
383
384 int end = searchContext.getEnd();
385 int start = searchContext.getStart();
386
387 if (isFilterSearch() && (permissionChecker != null)) {
388 searchContext.setEnd(end + INDEX_FILTER_SEARCH_LIMIT);
389 searchContext.setStart(0);
390 }
391
392 Hits hits = SearchEngineUtil.search(searchContext, fullQuery);
393
394 searchContext.setEnd(end);
395 searchContext.setStart(start);
396
397 if (isFilterSearch() && (permissionChecker != null)) {
398 hits = filterSearch(hits, permissionChecker, searchContext);
399 }
400
401 return hits;
402 }
403 catch (SearchException se) {
404 throw se;
405 }
406 catch (Exception e) {
407 throw new SearchException(e);
408 }
409 }
410
411 public void unregisterIndexerPostProcessor(
412 IndexerPostProcessor indexerPostProcessor) {
413
414 List<IndexerPostProcessor> indexerPostProcessorsList =
415 ListUtil.fromArray(_indexerPostProcessors);
416
417 indexerPostProcessorsList.remove(indexerPostProcessor);
418
419 _indexerPostProcessors = indexerPostProcessorsList.toArray(
420 new IndexerPostProcessor[indexerPostProcessorsList.size()]);
421 }
422
423
427 protected void addLocalizedSearchTerm(
428 BooleanQuery searchQuery, SearchContext searchContext, String field,
429 boolean like)
430 throws Exception {
431
432 addSearchLocalizedTerm(searchQuery, searchContext, field, like);
433 }
434
435 protected void addSearchArrayQuery(
436 BooleanQuery searchQuery, SearchContext searchContext, String field)
437 throws Exception {
438
439 if (Validator.isNull(field)) {
440 return;
441 }
442
443 Object fieldValues = searchContext.getAttribute(field);
444
445 if (fieldValues == null) {
446 return;
447 }
448
449 BooleanQuery fieldQuery = null;
450
451 if (fieldValues instanceof int[]) {
452 int[] fieldValuesArray = (int[])fieldValues;
453
454 if (fieldValuesArray.length == 0) {
455 return;
456 }
457
458 fieldQuery = BooleanQueryFactoryUtil.create(searchContext);
459
460 for (int fieldValue : fieldValuesArray) {
461 fieldQuery.addTerm(field, fieldValue);
462 }
463 }
464 else if (fieldValues instanceof Integer[]) {
465 Integer[] fieldValuesArray = (Integer[])fieldValues;
466
467 if (fieldValuesArray.length == 0) {
468 return;
469 }
470
471 fieldQuery = BooleanQueryFactoryUtil.create(searchContext);
472
473 for (Integer fieldValue : fieldValuesArray) {
474 fieldQuery.addTerm(field, fieldValue);
475 }
476 }
477 else if (fieldValues instanceof long[]) {
478 long[] fieldValuesArray = (long[])fieldValues;
479
480 if (fieldValuesArray.length == 0) {
481 return;
482 }
483
484 fieldQuery = BooleanQueryFactoryUtil.create(searchContext);
485
486 for (long fieldValue : fieldValuesArray) {
487 fieldQuery.addTerm(field, fieldValue);
488 }
489 }
490 else if (fieldValues instanceof Long[]) {
491 Long[] fieldValuesArray = (Long[])fieldValues;
492
493 if (fieldValuesArray.length == 0) {
494 return;
495 }
496
497 fieldQuery = BooleanQueryFactoryUtil.create(searchContext);
498
499 for (Long fieldValue : fieldValuesArray) {
500 fieldQuery.addTerm(field, fieldValue);
501 }
502 }
503 else if (fieldValues instanceof short[]) {
504 short[] fieldValuesArray = (short[])fieldValues;
505
506 if (fieldValuesArray.length == 0) {
507 return;
508 }
509
510 fieldQuery = BooleanQueryFactoryUtil.create(searchContext);
511
512 for (short fieldValue : fieldValuesArray) {
513 fieldQuery.addTerm(field, fieldValue);
514 }
515 }
516 else if (fieldValues instanceof Short[]) {
517 Short[] fieldValuesArray = (Short[])fieldValues;
518
519 if (fieldValuesArray.length == 0) {
520 return;
521 }
522
523 fieldQuery = BooleanQueryFactoryUtil.create(searchContext);
524
525 for (Short fieldValue : fieldValuesArray) {
526 fieldQuery.addTerm(field, fieldValue);
527 }
528 }
529
530 if (fieldQuery != null) {
531 if (searchContext.isAndSearch()) {
532 searchQuery.add(fieldQuery, BooleanClauseOccur.MUST);
533 }
534 else {
535 searchQuery.add(fieldQuery, BooleanClauseOccur.SHOULD);
536 }
537 }
538 }
539
540 protected void addSearchAssetCategoryIds(
541 BooleanQuery contextQuery, SearchContext searchContext)
542 throws Exception {
543
544 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
545
546 multiValueFacet.setFieldName(Field.ASSET_CATEGORY_IDS);
547 multiValueFacet.setStatic(true);
548
549 searchContext.addFacet(multiValueFacet);
550 }
551
552 protected void addSearchAssetCategoryTitles(
553 Document document, String field, List<AssetCategory> assetCategories) {
554
555 Map<Locale, List<String>> assetCategoryTitles =
556 new HashMap<Locale, List<String>>();
557
558 Locale defaultLocale = LocaleUtil.getDefault();
559
560 for (AssetCategory assetCategory : assetCategories) {
561 Map<Locale, String> titleMap = assetCategory.getTitleMap();
562
563 for (Map.Entry<Locale, String> entry : titleMap.entrySet()) {
564 Locale locale = entry.getKey();
565 String title = entry.getValue();
566
567 if (Validator.isNull(title)) {
568 continue;
569 }
570
571 List<String> titles = assetCategoryTitles.get(locale);
572
573 if (titles == null) {
574 titles = new ArrayList<String>();
575
576 assetCategoryTitles.put(locale, titles);
577 }
578
579 titles.add(title);
580 }
581 }
582
583 for (Map.Entry<Locale, List<String>> entry :
584 assetCategoryTitles.entrySet()) {
585
586 Locale locale = entry.getKey();
587 List<String> titles = entry.getValue();
588
589 String[] titlesArray = titles.toArray(new String[0]);
590
591 if (locale.equals(defaultLocale)) {
592 document.addKeyword(field, titlesArray);
593 }
594
595 document.addKeyword(
596 field.concat(StringPool.UNDERLINE).concat(locale.toString()),
597 titlesArray);
598 }
599 }
600
601 protected void addSearchAssetTagNames(
602 BooleanQuery contextQuery, SearchContext searchContext)
603 throws Exception {
604
605 MultiValueFacet multiValueFacet = new MultiValueFacet(searchContext);
606
607 multiValueFacet.setFieldName(Field.ASSET_TAG_NAMES);
608 multiValueFacet.setStatic(true);
609
610 searchContext.addFacet(multiValueFacet);
611 }
612
613 protected void addSearchDDMStruture(
614 BooleanQuery searchQuery, SearchContext searchContext,
615 DDMStructure ddmStructure)
616 throws Exception {
617
618 Set<String> fieldNames = ddmStructure.getFieldNames();
619
620 for (String fieldName : fieldNames) {
621 String name = DDMIndexerUtil.encodeName(
622 ddmStructure.getStructureId(), fieldName);
623
624 addSearchTerm(searchQuery, searchContext, name, false);
625 }
626 }
627
628 protected void addSearchEntryClassNames(
629 BooleanQuery contextQuery, SearchContext searchContext)
630 throws Exception {
631
632 Facet facet = new AssetEntriesFacet(searchContext);
633
634 facet.setStatic(true);
635
636 searchContext.addFacet(facet);
637 }
638
639 protected void addSearchExpando(
640 BooleanQuery searchQuery, SearchContext searchContext,
641 String keywords)
642 throws Exception {
643
644 ExpandoBridge expandoBridge = ExpandoBridgeFactoryUtil.getExpandoBridge(
645 searchContext.getCompanyId(), getClassName(searchContext));
646
647 Set<String> attributeNames = SetUtil.fromEnumeration(
648 expandoBridge.getAttributeNames());
649
650 for (String attributeName : attributeNames) {
651 UnicodeProperties properties = expandoBridge.getAttributeProperties(
652 attributeName);
653
654 int indexType = GetterUtil.getInteger(
655 properties.getProperty(ExpandoColumnConstants.INDEX_TYPE));
656
657 if (indexType != ExpandoColumnConstants.INDEX_TYPE_NONE) {
658 String fieldName = ExpandoBridgeIndexerUtil.encodeFieldName(
659 attributeName);
660
661 if (Validator.isNotNull(keywords)) {
662 if (searchContext.isAndSearch()) {
663 searchQuery.addRequiredTerm(fieldName, keywords);
664 }
665 else {
666 searchQuery.addTerm(fieldName, keywords);
667 }
668 }
669 }
670 }
671 }
672
673 protected void addSearchGroupId(
674 BooleanQuery contextQuery, SearchContext searchContext)
675 throws Exception {
676
677 Facet facet = new ScopeFacet(searchContext);
678
679 facet.setStatic(true);
680
681 searchContext.addFacet(facet);
682 }
683
684 protected void addSearchKeywords(
685 BooleanQuery searchQuery, SearchContext searchContext)
686 throws Exception {
687
688 String keywords = searchContext.getKeywords();
689
690 if (Validator.isNull(keywords)) {
691 return;
692 }
693
694 searchQuery.addTerms(Field.KEYWORDS, keywords);
695
696 addSearchExpando(searchQuery, searchContext, keywords);
697 }
698
699 protected void addSearchLocalizedTerm(
700 BooleanQuery searchQuery, SearchContext searchContext, String field,
701 boolean like)
702 throws Exception {
703
704 addSearchTerm(searchQuery, searchContext, field, like);
705 addSearchTerm(
706 searchQuery, searchContext,
707 DocumentImpl.getLocalizedName(searchContext.getLocale(), field),
708 like);
709 }
710
711 protected void addSearchTerm(
712 BooleanQuery searchQuery, SearchContext searchContext, String field,
713 boolean like)
714 throws Exception {
715
716 if (Validator.isNull(field)) {
717 return;
718 }
719
720 String value = String.valueOf(searchContext.getAttribute(field));
721
722 if (Validator.isNull(value)) {
723 value = searchContext.getKeywords();
724 }
725
726 if (Validator.isNull(value)) {
727 return;
728 }
729
730 if (searchContext.isAndSearch()) {
731 searchQuery.addRequiredTerm(field, value, like);
732 }
733 else {
734 searchQuery.addTerm(field, value, like);
735 }
736 }
737
738 protected void addStagingGroupKeyword(Document document, long groupId)
739 throws Exception {
740
741 if (!isStagingAware()) {
742 return;
743 }
744
745 boolean stagingGroup = false;
746
747 Group group = GroupLocalServiceUtil.getGroup(groupId);
748
749 if (group.isLayout()) {
750 group = GroupLocalServiceUtil.getGroup(group.getParentGroupId());
751 }
752
753 if (group.isStagingGroup()) {
754 stagingGroup = true;
755 }
756
757 document.addKeyword(Field.STAGING_GROUP, stagingGroup);
758 }
759
760 protected BooleanQuery createFullQuery(
761 BooleanQuery contextQuery, SearchContext searchContext)
762 throws Exception {
763
764 BooleanQuery searchQuery = BooleanQueryFactoryUtil.create(
765 searchContext);
766
767 addSearchKeywords(searchQuery, searchContext);
768 postProcessSearchQuery(searchQuery, searchContext);
769
770 for (IndexerPostProcessor indexerPostProcessor :
771 _indexerPostProcessors) {
772
773 indexerPostProcessor.postProcessSearchQuery(
774 searchQuery, searchContext);
775 }
776
777 Map<String, Facet> facets = searchContext.getFacets();
778
779 for (Facet facet : facets.values()) {
780 BooleanClause facetClause = facet.getFacetClause();
781
782 if (facetClause != null) {
783 contextQuery.add(
784 facetClause.getQuery(),
785 facetClause.getBooleanClauseOccur());
786 }
787 }
788
789 BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
790
791 fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
792
793 if (searchQuery.hasClauses()) {
794 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
795 }
796
797 BooleanClause[] booleanClauses = searchContext.getBooleanClauses();
798
799 if (booleanClauses != null) {
800 for (BooleanClause booleanClause : booleanClauses) {
801 fullQuery.add(
802 booleanClause.getQuery(),
803 booleanClause.getBooleanClauseOccur());
804 }
805 }
806
807 postProcessFullQuery(fullQuery, searchContext);
808
809 for (IndexerPostProcessor indexerPostProcessor :
810 _indexerPostProcessors) {
811
812 indexerPostProcessor.postProcessFullQuery(fullQuery, searchContext);
813 }
814
815 return fullQuery;
816 }
817
818 protected void deleteDocument(long companyId, long field1)
819 throws Exception {
820
821 deleteDocument(companyId, String.valueOf(field1));
822 }
823
824 protected void deleteDocument(long companyId, long field1, String field2)
825 throws Exception {
826
827 deleteDocument(companyId, String.valueOf(field1), field2);
828 }
829
830 protected void deleteDocument(long companyId, String field1)
831 throws Exception {
832
833 Document document = new DocumentImpl();
834
835 document.addUID(getPortletId(), field1);
836
837 SearchEngineUtil.deleteDocument(
838 getSearchEngineId(), companyId, document.get(Field.UID));
839 }
840
841 protected void deleteDocument(long companyId, String field1, String field2)
842 throws Exception {
843
844 Document document = new DocumentImpl();
845
846 document.addUID(getPortletId(), field1, field2);
847
848 SearchEngineUtil.deleteDocument(
849 getSearchEngineId(), companyId, document.get(Field.UID));
850 }
851
852 protected abstract void doDelete(Object obj) throws Exception;
853
854 protected abstract Document doGetDocument(Object obj) throws Exception;
855
856 protected String doGetSortField(String orderByCol) {
857 return orderByCol;
858 }
859
860 protected abstract Summary doGetSummary(
861 Document document, Locale locale, String snippet,
862 PortletURL portletURL)
863 throws Exception;
864
865 protected abstract void doReindex(Object obj) throws Exception;
866
867 protected abstract void doReindex(String className, long classPK)
868 throws Exception;
869
870 protected abstract void doReindex(String[] ids) throws Exception;
871
872 protected Hits filterSearch(
873 Hits hits, PermissionChecker permissionChecker,
874 SearchContext searchContext) {
875
876 List<Document> docs = new ArrayList<Document>();
877 List<Float> scores = new ArrayList<Float>();
878
879 int start = searchContext.getStart();
880 int end = searchContext.getEnd();
881
882 String paginationType = GetterUtil.getString(
883 searchContext.getAttribute("paginationType"), "more");
884
885 boolean hasMore = false;
886
887 Document[] documents = hits.getDocs();
888
889 for (int i = 0; i < documents.length; i++) {
890 try {
891 Document document = documents[i];
892
893 String entryClassName = document.get(Field.ENTRY_CLASS_NAME);
894 long entryClassPK = GetterUtil.getLong(
895 document.get(Field.ENTRY_CLASS_PK));
896
897 Indexer indexer = IndexerRegistryUtil.getIndexer(
898 entryClassName);
899
900 if ((indexer.isFilterSearch() &&
901 indexer.hasPermission(
902 permissionChecker, entryClassPK, ActionKeys.VIEW)) ||
903 !indexer.isFilterSearch() ||
904 !indexer.isPermissionAware()) {
905
906 docs.add(document);
907 scores.add(hits.score(i));
908 }
909 }
910 catch (Exception e) {
911 }
912
913 if (paginationType.equals("more") && (docs.size() > end)) {
914 hasMore = true;
915
916 break;
917 }
918 }
919
920 int length = docs.size();
921
922 if (hasMore) {
923 length = length + (end - start);
924 }
925
926 hits.setLength(length);
927
928 if ((start != QueryUtil.ALL_POS) && (end != QueryUtil.ALL_POS)) {
929 if (end > length) {
930 end = length;
931 }
932
933 docs = docs.subList(start, end);
934 }
935
936 hits.setDocs(docs.toArray(new Document[docs.size()]));
937 hits.setScores(scores.toArray(new Float[docs.size()]));
938
939 hits.setSearchTime(
940 (float)(System.currentTimeMillis() - hits.getStart()) /
941 Time.SECOND);
942
943 return hits;
944 }
945
946 protected Document getBaseModelDocument(
947 String portletId, BaseModel<?> baseModel)
948 throws SystemException {
949
950 Document document = new DocumentImpl();
951
952 String className = baseModel.getModelClassName();
953
954 long classPK = 0;
955 long resourcePrimKey = 0;
956
957 if (baseModel instanceof ResourcedModel) {
958 ResourcedModel resourcedModel = (ResourcedModel)baseModel;
959
960 classPK = resourcedModel.getResourcePrimKey();
961 resourcePrimKey = resourcedModel.getResourcePrimKey();
962 }
963 else {
964 classPK = (Long)baseModel.getPrimaryKeyObj();
965 }
966
967 document.addUID(portletId, classPK);
968
969 List<AssetCategory> assetCategories =
970 AssetCategoryLocalServiceUtil.getCategories(className, classPK);
971
972 long[] assetCategoryIds = StringUtil.split(
973 ListUtil.toString(
974 assetCategories, AssetCategory.CATEGORY_ID_ACCESSOR),
975 0L);
976
977 document.addKeyword(Field.ASSET_CATEGORY_IDS, assetCategoryIds);
978
979 addSearchAssetCategoryTitles(
980 document, Field.ASSET_CATEGORY_TITLES, assetCategories);
981
982 String[] assetTagNames = AssetTagLocalServiceUtil.getTagNames(
983 className, classPK);
984
985 document.addText(Field.ASSET_TAG_NAMES, assetTagNames);
986
987 document.addKeyword(Field.ENTRY_CLASS_NAME, className);
988 document.addKeyword(Field.ENTRY_CLASS_PK, classPK);
989 document.addKeyword(Field.PORTLET_ID, portletId);
990
991 if (resourcePrimKey > 0) {
992 document.addKeyword(Field.ROOT_ENTRY_CLASS_PK, resourcePrimKey);
993 }
994
995 if (baseModel instanceof AttachedModel) {
996 AttachedModel attachedModel = (AttachedModel)baseModel;
997
998 document.addKeyword(
999 Field.CLASS_NAME_ID, attachedModel.getClassNameId());
1000 document.addKeyword(Field.CLASS_PK, attachedModel.getClassPK());
1001 }
1002
1003 if (baseModel instanceof AuditedModel) {
1004 AuditedModel auditedModel = (AuditedModel)baseModel;
1005
1006 document.addKeyword(Field.COMPANY_ID, auditedModel.getCompanyId());
1007 document.addDate(Field.CREATE_DATE, auditedModel.getCreateDate());
1008 document.addDate(
1009 Field.MODIFIED_DATE, auditedModel.getModifiedDate());
1010 document.addKeyword(Field.USER_ID, auditedModel.getUserId());
1011
1012 String userName = PortalUtil.getUserName(
1013 auditedModel.getUserId(), auditedModel.getUserName());
1014
1015 document.addKeyword(Field.USER_NAME, userName, true);
1016 }
1017
1018 if (baseModel instanceof GroupedModel) {
1019 GroupedModel groupedModel = (GroupedModel)baseModel;
1020
1021 document.addKeyword(
1022 Field.GROUP_ID, getParentGroupId(groupedModel.getGroupId()));
1023 document.addKeyword(
1024 Field.SCOPE_GROUP_ID, groupedModel.getGroupId());
1025 }
1026
1027 if (baseModel instanceof WorkflowedModel) {
1028 WorkflowedModel workflowedModel = (WorkflowedModel)baseModel;
1029
1030 document.addKeyword(Field.STATUS, workflowedModel.getStatus());
1031 }
1032
1033 ExpandoBridgeIndexerUtil.addAttributes(
1034 document, baseModel.getExpandoBridge());
1035
1036 return document;
1037 }
1038
1039 protected String getClassName(SearchContext searchContext) {
1040 String[] classNames = getClassNames();
1041
1042 if (classNames.length != 1) {
1043 throw new UnsupportedOperationException(
1044 "Search method needs to be manually implemented for " +
1045 "indexers with more than one class name");
1046 }
1047
1048 return classNames[0];
1049 }
1050
1051 protected long getParentGroupId(long groupId) {
1052 long parentGroupId = groupId;
1053
1054 try {
1055 Group group = GroupLocalServiceUtil.getGroup(groupId);
1056
1057 if (group.isLayout()) {
1058 parentGroupId = group.getParentGroupId();
1059 }
1060 }
1061 catch (Exception e) {
1062 }
1063
1064 return parentGroupId;
1065 }
1066
1067 protected abstract String getPortletId(SearchContext searchContext);
1068
1069 protected void populateAddresses(
1070 Document document, List<Address> addresses, long regionId,
1071 long countryId)
1072 throws PortalException, SystemException {
1073
1074 List<String> cities = new ArrayList<String>();
1075
1076 List<String> countries = new ArrayList<String>();
1077
1078 if (countryId > 0) {
1079 try {
1080 Country country = CountryServiceUtil.getCountry(countryId);
1081
1082 countries.add(country.getName().toLowerCase());
1083 }
1084 catch (NoSuchCountryException nsce) {
1085 if (_log.isWarnEnabled()) {
1086 _log.warn(nsce.getMessage());
1087 }
1088 }
1089 }
1090
1091 List<String> regions = new ArrayList<String>();
1092
1093 if (regionId > 0) {
1094 try {
1095 Region region = RegionServiceUtil.getRegion(regionId);
1096
1097 regions.add(region.getName().toLowerCase());
1098 }
1099 catch (NoSuchRegionException nsre) {
1100 if (_log.isWarnEnabled()) {
1101 _log.warn(nsre.getMessage());
1102 }
1103 }
1104 }
1105
1106 List<String> streets = new ArrayList<String>();
1107 List<String> zips = new ArrayList<String>();
1108
1109 for (Address address : addresses) {
1110 cities.add(address.getCity().toLowerCase());
1111 countries.add(address.getCountry().getName().toLowerCase());
1112 regions.add(address.getRegion().getName().toLowerCase());
1113 streets.add(address.getStreet1().toLowerCase());
1114 streets.add(address.getStreet2().toLowerCase());
1115 streets.add(address.getStreet3().toLowerCase());
1116 zips.add(address.getZip().toLowerCase());
1117 }
1118
1119 document.addText("city", cities.toArray(new String[cities.size()]));
1120 document.addText(
1121 "country", countries.toArray(new String[countries.size()]));
1122 document.addText("region", regions.toArray(new String[regions.size()]));
1123 document.addText("street", streets.toArray(new String[streets.size()]));
1124 document.addText("zip", zips.toArray(new String[zips.size()]));
1125 }
1126
1127 protected void postProcessFullQuery(
1128 BooleanQuery fullQuery, SearchContext searchContext)
1129 throws Exception {
1130 }
1131
1132 protected void setStagingAware(boolean stagingAware) {
1133 _stagingAware = stagingAware;
1134 }
1135
1136 private static final boolean _FILTER_SEARCH = false;
1137
1138 private static final boolean _INDEXER_ENABLED = true;
1139
1140 private static final boolean _PERMISSION_AWARE = false;
1141
1142 private static Log _log = LogFactoryUtil.getLog(BaseIndexer.class);
1143
1144 private IndexerPostProcessor[] _indexerPostProcessors =
1145 new IndexerPostProcessor[0];
1146 private String _searchEngineId;
1147 private boolean _stagingAware = true;
1148
1149 }