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