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