001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.documentlibrary.util;
016    
017    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
018    import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
019    import com.liferay.portal.kernel.dao.orm.Projection;
020    import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
021    import com.liferay.portal.kernel.dao.orm.ProjectionList;
022    import com.liferay.portal.kernel.dao.orm.Property;
023    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
024    import com.liferay.portal.kernel.exception.PortalException;
025    import com.liferay.portal.kernel.exception.SystemException;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
029    import com.liferay.portal.kernel.portlet.LiferayWindowState;
030    import com.liferay.portal.kernel.search.BaseIndexer;
031    import com.liferay.portal.kernel.search.BooleanClauseOccur;
032    import com.liferay.portal.kernel.search.BooleanQuery;
033    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
034    import com.liferay.portal.kernel.search.Document;
035    import com.liferay.portal.kernel.search.DocumentImpl;
036    import com.liferay.portal.kernel.search.Field;
037    import com.liferay.portal.kernel.search.SearchContext;
038    import com.liferay.portal.kernel.search.SearchEngineUtil;
039    import com.liferay.portal.kernel.search.SearchException;
040    import com.liferay.portal.kernel.search.Summary;
041    import com.liferay.portal.kernel.util.ArrayUtil;
042    import com.liferay.portal.kernel.util.GetterUtil;
043    import com.liferay.portal.kernel.util.ListUtil;
044    import com.liferay.portal.kernel.util.PropsKeys;
045    import com.liferay.portal.kernel.util.StringPool;
046    import com.liferay.portal.kernel.util.StringUtil;
047    import com.liferay.portal.kernel.util.Validator;
048    import com.liferay.portal.kernel.workflow.WorkflowConstants;
049    import com.liferay.portal.model.Group;
050    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
051    import com.liferay.portal.security.permission.ActionKeys;
052    import com.liferay.portal.security.permission.PermissionChecker;
053    import com.liferay.portal.service.GroupLocalServiceUtil;
054    import com.liferay.portal.util.PortalUtil;
055    import com.liferay.portal.util.PortletKeys;
056    import com.liferay.portal.util.PrefsPropsUtil;
057    import com.liferay.portal.util.PropsValues;
058    import com.liferay.portlet.asset.model.AssetCategory;
059    import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
060    import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
061    import com.liferay.portlet.bookmarks.service.BookmarksFolderLocalServiceUtil;
062    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
063    import com.liferay.portlet.documentlibrary.model.DLFileEntryMetadata;
064    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
065    import com.liferay.portlet.documentlibrary.model.DLFileVersion;
066    import com.liferay.portlet.documentlibrary.model.DLFolder;
067    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
068    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
069    import com.liferay.portlet.documentlibrary.service.DLFileEntryMetadataLocalServiceUtil;
070    import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
071    import com.liferay.portlet.documentlibrary.service.DLFolderLocalServiceUtil;
072    import com.liferay.portlet.documentlibrary.service.DLFolderServiceUtil;
073    import com.liferay.portlet.documentlibrary.service.permission.DLFileEntryPermission;
074    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
075    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
076    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
077    import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
078    import com.liferay.portlet.dynamicdatamapping.util.DDMIndexerUtil;
079    import com.liferay.portlet.expando.model.ExpandoBridge;
080    import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
081    import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
082    
083    import java.io.IOException;
084    import java.io.InputStream;
085    
086    import java.util.ArrayList;
087    import java.util.Collection;
088    import java.util.LinkedHashMap;
089    import java.util.List;
090    import java.util.Locale;
091    import java.util.Set;
092    import java.util.TreeSet;
093    
094    import javax.portlet.PortletRequest;
095    import javax.portlet.PortletURL;
096    import javax.portlet.WindowStateException;
097    
098    /**
099     * @author Brian Wing Shun Chan
100     * @author Raymond Augé
101     * @author Alexander Chow
102     */
103    public class DLIndexer extends BaseIndexer {
104    
105            public static final String[] CLASS_NAMES = {DLFileEntry.class.getName()};
106    
107            public static final String PORTLET_ID = PortletKeys.DOCUMENT_LIBRARY;
108    
109            public String[] getClassNames() {
110                    return CLASS_NAMES;
111            }
112    
113            public String getPortletId() {
114                    return PORTLET_ID;
115            }
116    
117            @Override
118            public boolean hasPermission(
119                            PermissionChecker permissionChecker, long entryClassPK,
120                            String actionId)
121                    throws Exception {
122    
123                    return DLFileEntryPermission.contains(
124                            permissionChecker, entryClassPK, ActionKeys.VIEW);
125            }
126    
127            @Override
128            public boolean isFilterSearch() {
129                    return _FILTER_SEARCH;
130            }
131    
132            @Override
133            public boolean isPermissionAware() {
134                    return _PERMISSION_AWARE;
135            }
136    
137            @Override
138            public void postProcessContextQuery(
139                            BooleanQuery contextQuery, SearchContext searchContext)
140                    throws Exception {
141    
142                    int status = GetterUtil.getInteger(
143                            searchContext.getAttribute(Field.STATUS),
144                            WorkflowConstants.STATUS_APPROVED);
145    
146                    if (status != WorkflowConstants.STATUS_ANY) {
147                            contextQuery.addRequiredTerm(Field.STATUS, status);
148                    }
149    
150                    long[] folderIds = searchContext.getFolderIds();
151    
152                    if ((folderIds != null) && (folderIds.length > 0)) {
153                            if (folderIds[0] == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
154                                    return;
155                            }
156    
157                            BooleanQuery folderIdsQuery = BooleanQueryFactoryUtil.create(
158                                    searchContext);
159    
160                            for (long folderId : folderIds) {
161                                    try {
162                                            DLFolderServiceUtil.getFolder(folderId);
163                                    }
164                                    catch (Exception e) {
165                                            continue;
166                                    }
167    
168                                    folderIdsQuery.addTerm(Field.FOLDER_ID, folderId);
169                            }
170    
171                            contextQuery.add(folderIdsQuery, BooleanClauseOccur.MUST);
172                    }
173            }
174    
175            @Override
176            public void postProcessSearchQuery(
177                            BooleanQuery searchQuery, SearchContext searchContext)
178                    throws Exception {
179    
180                    Set<DDMStructure> ddmStructuresSet = new TreeSet<DDMStructure>();
181    
182                    long[] groupIds = searchContext.getGroupIds();
183    
184                    if ((groupIds != null) && (groupIds.length > 0)) {
185                            List<DLFileEntryType> dlFileEntryTypes =
186                                    DLFileEntryTypeLocalServiceUtil.getFileEntryTypes(groupIds);
187    
188                            for (DLFileEntryType dlFileEntryType : dlFileEntryTypes) {
189                                    ddmStructuresSet.addAll(dlFileEntryType.getDDMStructures());
190                            }
191                    }
192    
193                    Group group = GroupLocalServiceUtil.getCompanyGroup(
194                            searchContext.getCompanyId());
195    
196                    DDMStructure tikaRawMetadataStructure =
197                            DDMStructureLocalServiceUtil.fetchStructure(
198                                    group.getGroupId(), "TikaRawMetadata");
199    
200                    if (tikaRawMetadataStructure != null) {
201                            ddmStructuresSet.add(tikaRawMetadataStructure);
202                    }
203    
204                    for (DDMStructure ddmStructure : ddmStructuresSet) {
205                            addSearchDDMStruture(searchQuery, searchContext, ddmStructure);
206                    }
207    
208                    addSearchTerm(searchQuery, searchContext, Field.USER_NAME, false);
209    
210                    addSearchTerm(searchQuery, searchContext, "extension", false);
211                    addSearchTerm(searchQuery, searchContext, "fileEntryTypeId", false);
212                    addSearchTerm(searchQuery, searchContext, "path", false);
213    
214                    LinkedHashMap<String, Object> params =
215                            (LinkedHashMap<String, Object>)searchContext.getAttribute("params");
216    
217                    if (params != null) {
218                            String expandoAttributes = (String)params.get("expandoAttributes");
219    
220                            if (Validator.isNotNull(expandoAttributes)) {
221                                    addSearchExpando(searchQuery, searchContext, expandoAttributes);
222                            }
223                    }
224            }
225    
226            protected void addFileEntryTypeAttributes(
227                            Document document, DLFileVersion dlFileVersion)
228                    throws PortalException, SystemException {
229    
230                    DLFileEntryType dlFileEntryType =
231                            DLFileEntryTypeLocalServiceUtil.getFileEntryType(
232                                    dlFileVersion.getFileEntryTypeId());
233    
234                    List<DDMStructure> ddmStructures = dlFileEntryType.getDDMStructures();
235    
236                    Group group = GroupLocalServiceUtil.getCompanyGroup(
237                            dlFileVersion.getCompanyId());
238    
239                    DDMStructure tikaRawMetadataStructure =
240                            DDMStructureLocalServiceUtil.fetchStructure(
241                                    group.getGroupId(), "TikaRawMetadata");
242    
243                    if (tikaRawMetadataStructure != null) {
244                            ddmStructures = ListUtil.copy(ddmStructures);
245    
246                            ddmStructures.add(tikaRawMetadataStructure);
247                    }
248    
249                    for (DDMStructure ddmStructure : ddmStructures) {
250                            Fields fields = null;
251    
252                            try {
253                                    DLFileEntryMetadata fileEntryMetadata =
254                                            DLFileEntryMetadataLocalServiceUtil.getFileEntryMetadata(
255                                                    ddmStructure.getStructureId(),
256                                                    dlFileVersion.getFileVersionId());
257    
258                                    fields = StorageEngineUtil.getFields(
259                                            fileEntryMetadata.getDDMStorageId());
260                            }
261                            catch (Exception e) {
262                            }
263    
264                            if (fields != null) {
265                                    DDMIndexerUtil.addAttributes(document, ddmStructure, fields);
266                            }
267                    }
268            }
269    
270            protected void addReindexCriteria(
271                    DynamicQuery dynamicQuery, long companyId) {
272    
273                    Property property = PropertyFactoryUtil.forName("companyId");
274    
275                    dynamicQuery.add(property.eq(companyId));
276            }
277    
278            protected void addReindexCriteria(
279                    DynamicQuery dynamicQuery, long groupId, long folderId) {
280    
281                    Property groupIdProperty = PropertyFactoryUtil.forName("groupId");
282    
283                    dynamicQuery.add(groupIdProperty.eq(groupId));
284    
285                    Property folderIdProperty = PropertyFactoryUtil.forName("folderId");
286    
287                    dynamicQuery.add(folderIdProperty.eq(folderId));
288            }
289    
290            @Override
291            protected void doDelete(Object obj) throws Exception {
292                    DLFileEntry dlFileEntry = (DLFileEntry)obj;
293    
294                    Document document = new DocumentImpl();
295    
296                    document.addUID(PORTLET_ID, dlFileEntry.getFileEntryId());
297    
298                    SearchEngineUtil.deleteDocument(
299                            getSearchEngineId(), dlFileEntry.getCompanyId(),
300                            document.get(Field.UID));
301            }
302    
303            @Override
304            protected Document doGetDocument(Object obj) throws Exception {
305                    DLFileEntry dlFileEntry = (DLFileEntry)obj;
306    
307                    if (_log.isDebugEnabled()) {
308                            _log.debug("Indexing document " + dlFileEntry);
309                    }
310    
311                    boolean indexContent = true;
312    
313                    InputStream is = null;
314    
315                    try {
316                            if (PropsValues.DL_FILE_INDEXING_MAX_SIZE == 0) {
317                                    indexContent = false;
318                            }
319                            else if (PropsValues.DL_FILE_INDEXING_MAX_SIZE != -1) {
320                                    if (dlFileEntry.getSize() >
321                                                    PropsValues.DL_FILE_INDEXING_MAX_SIZE) {
322    
323                                            indexContent = false;
324                                    }
325                            }
326    
327                            if (indexContent) {
328                                    String[] ignoreExtensions = PrefsPropsUtil.getStringArray(
329                                            PropsKeys.DL_FILE_INDEXING_IGNORE_EXTENSIONS,
330                                            StringPool.COMMA);
331    
332                                    if (ArrayUtil.contains(
333                                                    ignoreExtensions,
334                                                    StringPool.PERIOD + dlFileEntry.getExtension())) {
335    
336                                            indexContent = false;
337                                    }
338                            }
339    
340                            if (indexContent) {
341                                    is = dlFileEntry.getFileVersion().getContentStream(false);
342                            }
343                    }
344                    catch (Exception e) {
345                    }
346    
347                    if (indexContent && (is == null)) {
348                            if (_log.isDebugEnabled()) {
349                                    _log.debug(
350                                            "Document " + dlFileEntry + " does not have any content");
351                            }
352    
353                            return null;
354                    }
355    
356                    try {
357                            Document document = new DocumentImpl();
358    
359                            long fileEntryId = dlFileEntry.getFileEntryId();
360    
361                            document.addUID(PORTLET_ID, fileEntryId);
362    
363                            List<AssetCategory> assetCategories =
364                                    AssetCategoryLocalServiceUtil.getCategories(
365                                            DLFileEntry.class.getName(), fileEntryId);
366    
367                            long[] assetCategoryIds = StringUtil.split(
368                                    ListUtil.toString(
369                                            assetCategories, AssetCategory.CATEGORY_ID_ACCESSOR),
370                                    0L);
371    
372                            document.addKeyword(Field.ASSET_CATEGORY_IDS, assetCategoryIds);
373    
374                            addSearchAssetCategoryTitles(
375                                    document, Field.ASSET_CATEGORY_TITLES, assetCategories);
376    
377                            String[] assetTagNames = AssetTagLocalServiceUtil.getTagNames(
378                                    DLFileEntry.class.getName(), fileEntryId);
379    
380                            document.addKeyword(Field.ASSET_TAG_NAMES, assetTagNames);
381    
382                            document.addKeyword(Field.COMPANY_ID, dlFileEntry.getCompanyId());
383    
384                            if (indexContent) {
385                                    try {
386                                            document.addFile(Field.CONTENT, is, dlFileEntry.getTitle());
387                                    }
388                                    catch (IOException ioe) {
389                                            throw new SearchException(
390                                                    "Cannot extract text from file" + dlFileEntry);
391                                    }
392                            }
393    
394                            document.addText(Field.DESCRIPTION, dlFileEntry.getDescription());
395                            document.addKeyword(
396                                    Field.ENTRY_CLASS_NAME, DLFileEntry.class.getName());
397                            document.addKeyword(Field.ENTRY_CLASS_PK, fileEntryId);
398                            document.addKeyword(Field.FOLDER_ID, dlFileEntry.getFolderId());
399                            document.addKeyword(
400                                    Field.GROUP_ID, getParentGroupId(dlFileEntry.getGroupId()));
401                            document.addDate(
402                                    Field.MODIFIED_DATE, dlFileEntry.getModifiedDate());
403                            document.addKeyword(Field.PORTLET_ID, PORTLET_ID);
404                            document.addText(
405                                    Field.PROPERTIES, dlFileEntry.getLuceneProperties());
406                            document.addKeyword(Field.SCOPE_GROUP_ID, dlFileEntry.getGroupId());
407    
408                            DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
409    
410                            document.addKeyword(Field.STATUS, dlFileVersion.getStatus());
411                            document.addText(Field.TITLE, dlFileEntry.getTitle());
412    
413                            long userId = dlFileEntry.getUserId();
414    
415                            document.addKeyword(Field.USER_ID, userId);
416                            document.addKeyword(
417                                    Field.USER_NAME,
418                                    PortalUtil.getUserName(userId, dlFileEntry.getUserName()),
419                                    true);
420    
421                            document.addKeyword(
422                                    "dataRepositoryId", dlFileEntry.getDataRepositoryId());
423                            document.addKeyword("extension", dlFileEntry.getExtension());
424                            document.addKeyword(
425                                    "fileEntryTypeId", dlFileEntry.getFileEntryTypeId());
426                            document.addKeyword("path", dlFileEntry.getTitle());
427    
428                            ExpandoBridge expandoBridge =
429                                    ExpandoBridgeFactoryUtil.getExpandoBridge(
430                                            dlFileEntry.getCompanyId(), DLFileEntry.class.getName(),
431                                            dlFileVersion.getFileVersionId());
432    
433                            ExpandoBridgeIndexerUtil.addAttributes(document, expandoBridge);
434    
435                            addFileEntryTypeAttributes(document, dlFileVersion);
436    
437                            if (_log.isDebugEnabled()) {
438                                    _log.debug("Document " + dlFileEntry + " indexed successfully");
439                            }
440    
441                            return document;
442                    }
443                    finally {
444                            if (is != null) {
445                                    try {
446                                            is.close();
447                                    }
448                                    catch (IOException ioe) {
449                                    }
450                            }
451                    }
452            }
453    
454            @Override
455            protected Summary doGetSummary(
456                    Document document, Locale locale, String snippet,
457                    PortletURL portletURL) {
458    
459                    LiferayPortletURL liferayPortletURL = (LiferayPortletURL)portletURL;
460    
461                    liferayPortletURL.setLifecycle(PortletRequest.ACTION_PHASE);
462    
463                    try {
464                            liferayPortletURL.setWindowState(LiferayWindowState.EXCLUSIVE);
465                    }
466                    catch (WindowStateException wse) {
467                    }
468    
469                    String title = document.get(Field.TITLE);
470    
471                    String content = snippet;
472    
473                    if (Validator.isNull(snippet)) {
474                            content = StringUtil.shorten(document.get(Field.CONTENT), 200);
475                    }
476    
477                    String fileEntryId = document.get(Field.ENTRY_CLASS_PK);
478    
479                    portletURL.setParameter("struts_action", "/document_library/get_file");
480                    portletURL.setParameter("fileEntryId", fileEntryId);
481    
482                    return new Summary(title, content, portletURL);
483            }
484    
485            @Override
486            protected void doReindex(Object obj) throws Exception {
487                    DLFileEntry dlFileEntry = (DLFileEntry)obj;
488    
489                    DLFileVersion dlFileVersion = dlFileEntry.getLatestFileVersion(true);
490    
491                    if (!dlFileVersion.isApproved()) {
492                            return;
493                    }
494    
495                    Document document = getDocument(dlFileEntry);
496    
497                    if (document != null) {
498                            SearchEngineUtil.updateDocument(
499                                    getSearchEngineId(), dlFileEntry.getCompanyId(), document);
500                    }
501            }
502    
503            @Override
504            protected void doReindex(String className, long classPK) throws Exception {
505                    DLFileEntry dlFileEntry = DLFileEntryLocalServiceUtil.getFileEntry(
506                            classPK);
507    
508                    doReindex(dlFileEntry);
509            }
510    
511            @Override
512            protected void doReindex(String[] ids) throws Exception {
513                    if (ids.length == 1) {
514                            long companyId = GetterUtil.getLong(ids[0]);
515    
516                            reindexFolders(companyId);
517                            reindexRoot(companyId);
518                    }
519                    else {
520                            long companyId = GetterUtil.getLong(ids[0]);
521                            long groupId = GetterUtil.getLong(ids[2]);
522                            long dataRepositoryId = GetterUtil.getLong(ids[3]);
523    
524                            reindexFileEntries(companyId, groupId, dataRepositoryId);
525                    }
526            }
527    
528            @Override
529            protected String getPortletId(SearchContext searchContext) {
530                    return PORTLET_ID;
531            }
532    
533            protected void reindexFileEntries(
534                            long companyId, long groupId, long dataRepositoryId)
535                    throws Exception {
536    
537                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
538                            DLFileEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
539    
540                    Projection minFileEntryIdProjection = ProjectionFactoryUtil.min(
541                            "fileEntryId");
542                    Projection maxFileEntryIdProjection = ProjectionFactoryUtil.max(
543                            "fileEntryId");
544    
545                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
546    
547                    projectionList.add(minFileEntryIdProjection);
548                    projectionList.add(maxFileEntryIdProjection);
549    
550                    dynamicQuery.setProjection(projectionList);
551    
552                    long folderId = DLFolderConstants.getFolderId(
553                            groupId, dataRepositoryId);
554    
555                    addReindexCriteria(dynamicQuery, groupId, folderId);
556    
557                    List<Object[]> results = DLFileEntryLocalServiceUtil.dynamicQuery(
558                            dynamicQuery);
559    
560                    Object[] minAndMaxFileEntryIds = results.get(0);
561    
562                    if ((minAndMaxFileEntryIds[0] == null) ||
563                            (minAndMaxFileEntryIds[1] == null)) {
564    
565                            return;
566                    }
567    
568                    long minFileEntryId = (Long)minAndMaxFileEntryIds[0];
569                    long maxFileEntryId = (Long)minAndMaxFileEntryIds[1];
570    
571                    long startFileEntryId = minFileEntryId;
572                    long endFileEntryId = startFileEntryId + DEFAULT_INTERVAL;
573    
574                    while (startFileEntryId <= maxFileEntryId) {
575                            reindexFileEntries(
576                                    companyId, groupId, folderId, startFileEntryId, endFileEntryId);
577    
578                            startFileEntryId = endFileEntryId;
579                            endFileEntryId += DEFAULT_INTERVAL;
580                    }
581            }
582    
583            protected void reindexFileEntries(
584                            long companyId, long groupId, long folderId, long startFileEntryId,
585                            long endFileEntryId)
586                    throws Exception {
587    
588                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
589                            DLFileEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
590    
591                    Property property = PropertyFactoryUtil.forName("fileEntryId");
592    
593                    dynamicQuery.add(property.ge(startFileEntryId));
594                    dynamicQuery.add(property.lt(endFileEntryId));
595    
596                    addReindexCriteria(dynamicQuery, groupId, folderId);
597    
598                    List<DLFileEntry> dlFileEntries =
599                            DLFileEntryLocalServiceUtil.dynamicQuery(dynamicQuery);
600    
601                    if (dlFileEntries.isEmpty()) {
602                            return;
603                    }
604    
605                    Collection<Document> documents = new ArrayList<Document>(
606                            dlFileEntries.size());
607    
608                    for (DLFileEntry dlFileEntry : dlFileEntries) {
609                            Document document = getDocument(dlFileEntry);
610    
611                            if (document != null) {
612                                    documents.add(document);
613                            }
614                    }
615    
616                    SearchEngineUtil.updateDocuments(
617                            getSearchEngineId(), companyId, documents);
618            }
619    
620            protected void reindexFolders(long companyId) throws Exception {
621                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
622                            DLFolder.class, PACLClassLoaderUtil.getPortalClassLoader());
623    
624                    Projection minFolderIdProjection = ProjectionFactoryUtil.min(
625                            "folderId");
626                    Projection maxFolderIdProjection = ProjectionFactoryUtil.max(
627                            "folderId");
628    
629                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
630    
631                    projectionList.add(minFolderIdProjection);
632                    projectionList.add(maxFolderIdProjection);
633    
634                    dynamicQuery.setProjection(projectionList);
635    
636                    addReindexCriteria(dynamicQuery, companyId);
637    
638                    List<Object[]> results = BookmarksFolderLocalServiceUtil.dynamicQuery(
639                            dynamicQuery);
640    
641                    Object[] minAndMaxFolderIds = results.get(0);
642    
643                    if ((minAndMaxFolderIds[0] == null) ||
644                            (minAndMaxFolderIds[1] == null)) {
645    
646                            return;
647                    }
648    
649                    long minFolderId = (Long)minAndMaxFolderIds[0];
650                    long maxFolderId = (Long)minAndMaxFolderIds[1];
651    
652                    long startFolderId = minFolderId;
653                    long endFolderId = startFolderId + DEFAULT_INTERVAL;
654    
655                    while (startFolderId <= maxFolderId) {
656                            reindexFolders(companyId, startFolderId, endFolderId);
657    
658                            startFolderId = endFolderId;
659                            endFolderId += DEFAULT_INTERVAL;
660                    }
661            }
662    
663            protected void reindexFolders(
664                            long companyId, long startFolderId, long endFolderId)
665                    throws Exception {
666    
667                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
668                            DLFolder.class, PACLClassLoaderUtil.getPortalClassLoader());
669    
670                    Property property = PropertyFactoryUtil.forName("folderId");
671    
672                    dynamicQuery.add(property.ge(startFolderId));
673                    dynamicQuery.add(property.lt(endFolderId));
674    
675                    addReindexCriteria(dynamicQuery, companyId);
676    
677                    List<DLFolder> dlFolders = DLFolderLocalServiceUtil.dynamicQuery(
678                            dynamicQuery);
679    
680                    for (DLFolder dlFolder : dlFolders) {
681                            String portletId = PortletKeys.DOCUMENT_LIBRARY;
682                            long groupId = dlFolder.getGroupId();
683                            long folderId = dlFolder.getFolderId();
684    
685                            String[] newIds = {
686                                    String.valueOf(companyId), portletId, String.valueOf(groupId),
687                                    String.valueOf(folderId)
688                            };
689    
690                            reindex(newIds);
691                    }
692            }
693    
694            protected void reindexRoot(long companyId) throws Exception {
695                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
696                            Group.class, PACLClassLoaderUtil.getPortalClassLoader());
697    
698                    Projection minGroupIdProjection = ProjectionFactoryUtil.min("groupId");
699                    Projection maxGroupIdProjection = ProjectionFactoryUtil.max("groupId");
700    
701                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
702    
703                    projectionList.add(minGroupIdProjection);
704                    projectionList.add(maxGroupIdProjection);
705    
706                    dynamicQuery.setProjection(projectionList);
707    
708                    addReindexCriteria(dynamicQuery, companyId);
709    
710                    List<Object[]> results = GroupLocalServiceUtil.dynamicQuery(
711                            dynamicQuery);
712    
713                    Object[] minAndMaxGroupIds = results.get(0);
714    
715                    if ((minAndMaxGroupIds[0] == null) || (minAndMaxGroupIds[1] == null)) {
716                            return;
717                    }
718    
719                    long minGroupId = (Long)minAndMaxGroupIds[0];
720                    long maxGroupId = (Long)minAndMaxGroupIds[1];
721    
722                    long startGroupId = minGroupId;
723                    long endGroupId = startGroupId + DEFAULT_INTERVAL;
724    
725                    while (startGroupId <= maxGroupId) {
726                            reindexRoot(companyId, startGroupId, endGroupId);
727    
728                            startGroupId = endGroupId;
729                            endGroupId += DEFAULT_INTERVAL;
730                    }
731            }
732    
733            protected void reindexRoot(
734                            long companyId, long startGroupId, long endGroupId)
735                    throws Exception {
736    
737                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
738                            Group.class, PACLClassLoaderUtil.getPortalClassLoader());
739    
740                    Property property = PropertyFactoryUtil.forName("groupId");
741    
742                    dynamicQuery.add(property.ge(startGroupId));
743                    dynamicQuery.add(property.lt(endGroupId));
744    
745                    addReindexCriteria(dynamicQuery, companyId);
746    
747                    List<Group> groups = GroupLocalServiceUtil.dynamicQuery(dynamicQuery);
748    
749                    for (Group group : groups) {
750                            String portletId = PortletKeys.DOCUMENT_LIBRARY;
751                            long groupId = group.getGroupId();
752                            long folderId = groupId;
753    
754                            String[] newIds = {
755                                    String.valueOf(companyId), portletId, String.valueOf(groupId),
756                                    String.valueOf(folderId)
757                            };
758    
759                            reindex(newIds);
760                    }
761            }
762    
763            private static final boolean _FILTER_SEARCH = true;
764    
765            private static final boolean _PERMISSION_AWARE = true;
766    
767            private static Log _log = LogFactoryUtil.getLog(DLIndexer.class);
768    
769    }