001    /**
002     * Copyright (c) 2000-2013 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.portlet.documentlibrary.service.impl;
016    
017    import com.liferay.portal.ExpiredLockException;
018    import com.liferay.portal.InvalidLockException;
019    import com.liferay.portal.NoSuchLockException;
020    import com.liferay.portal.NoSuchWorkflowDefinitionLinkException;
021    import com.liferay.portal.kernel.dao.orm.QueryDefinition;
022    import com.liferay.portal.kernel.dao.orm.QueryUtil;
023    import com.liferay.portal.kernel.exception.PortalException;
024    import com.liferay.portal.kernel.exception.SystemException;
025    import com.liferay.portal.kernel.increment.BufferedIncrement;
026    import com.liferay.portal.kernel.increment.DateOverrideIncrement;
027    import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
028    import com.liferay.portal.kernel.log.Log;
029    import com.liferay.portal.kernel.log.LogFactoryUtil;
030    import com.liferay.portal.kernel.search.Indexable;
031    import com.liferay.portal.kernel.search.IndexableType;
032    import com.liferay.portal.kernel.search.Indexer;
033    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
034    import com.liferay.portal.kernel.systemevent.SystemEvent;
035    import com.liferay.portal.kernel.util.ObjectValuePair;
036    import com.liferay.portal.kernel.util.OrderByComparator;
037    import com.liferay.portal.kernel.util.ParamUtil;
038    import com.liferay.portal.kernel.util.StringPool;
039    import com.liferay.portal.kernel.util.TreeModelFinder;
040    import com.liferay.portal.kernel.util.TreePathUtil;
041    import com.liferay.portal.kernel.util.Validator;
042    import com.liferay.portal.kernel.workflow.WorkflowConstants;
043    import com.liferay.portal.model.Group;
044    import com.liferay.portal.model.Lock;
045    import com.liferay.portal.model.Repository;
046    import com.liferay.portal.model.ResourceConstants;
047    import com.liferay.portal.model.SystemEventConstants;
048    import com.liferay.portal.model.User;
049    import com.liferay.portal.model.WorkflowDefinitionLink;
050    import com.liferay.portal.repository.liferayrepository.model.LiferayFolder;
051    import com.liferay.portal.service.ServiceContext;
052    import com.liferay.portlet.documentlibrary.DuplicateFileException;
053    import com.liferay.portlet.documentlibrary.DuplicateFolderNameException;
054    import com.liferay.portlet.documentlibrary.FolderNameException;
055    import com.liferay.portlet.documentlibrary.InvalidFolderException;
056    import com.liferay.portlet.documentlibrary.NoSuchDirectoryException;
057    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
058    import com.liferay.portlet.documentlibrary.NoSuchFolderException;
059    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
060    import com.liferay.portlet.documentlibrary.model.DLFileEntryTypeConstants;
061    import com.liferay.portlet.documentlibrary.model.DLFolder;
062    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
063    import com.liferay.portlet.documentlibrary.model.impl.DLFolderImpl;
064    import com.liferay.portlet.documentlibrary.service.base.DLFolderLocalServiceBaseImpl;
065    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
066    import com.liferay.portlet.documentlibrary.util.comparator.FolderIdComparator;
067    
068    import java.io.Serializable;
069    
070    import java.util.ArrayList;
071    import java.util.Collections;
072    import java.util.Date;
073    import java.util.List;
074    import java.util.Map;
075    
076    /**
077     * @author Brian Wing Shun Chan
078     * @author Alexander Chow
079     */
080    public class DLFolderLocalServiceImpl extends DLFolderLocalServiceBaseImpl {
081    
082            @Override
083            public DLFolder addFolder(
084                            long userId, long groupId, long repositoryId, boolean mountPoint,
085                            long parentFolderId, String name, String description,
086                            boolean hidden, ServiceContext serviceContext)
087                    throws PortalException, SystemException {
088    
089                    // Folder
090    
091                    User user = userPersistence.findByPrimaryKey(userId);
092                    parentFolderId = getParentFolderId(
093                            groupId, repositoryId, parentFolderId);
094                    Date now = new Date();
095    
096                    validateFolder(groupId, parentFolderId, name);
097    
098                    long folderId = counterLocalService.increment();
099    
100                    DLFolder dlFolder = dlFolderPersistence.create(folderId);
101    
102                    dlFolder.setUuid(serviceContext.getUuid());
103                    dlFolder.setGroupId(groupId);
104                    dlFolder.setCompanyId(user.getCompanyId());
105                    dlFolder.setUserId(user.getUserId());
106                    dlFolder.setUserName(user.getFullName());
107                    dlFolder.setCreateDate(serviceContext.getCreateDate(now));
108                    dlFolder.setModifiedDate(serviceContext.getModifiedDate(now));
109                    dlFolder.setRepositoryId(repositoryId);
110                    dlFolder.setMountPoint(mountPoint);
111                    dlFolder.setParentFolderId(parentFolderId);
112                    dlFolder.setTreePath(dlFolder.buildTreePath());
113                    dlFolder.setName(name);
114                    dlFolder.setDescription(description);
115                    dlFolder.setLastPostDate(now);
116                    dlFolder.setHidden(hidden);
117                    dlFolder.setOverrideFileEntryTypes(false);
118                    dlFolder.setExpandoBridgeAttributes(serviceContext);
119    
120                    dlFolderPersistence.update(dlFolder);
121    
122                    // Resources
123    
124                    if (serviceContext.isAddGroupPermissions() ||
125                            serviceContext.isAddGuestPermissions()) {
126    
127                            addFolderResources(
128                                    dlFolder, serviceContext.isAddGroupPermissions(),
129                                    serviceContext.isAddGuestPermissions());
130                    }
131                    else {
132                            if (serviceContext.isDeriveDefaultPermissions()) {
133                                    serviceContext.deriveDefaultPermissions(
134                                            repositoryId, DLFolderConstants.getClassName());
135                            }
136    
137                            addFolderResources(
138                                    dlFolder, serviceContext.getGroupPermissions(),
139                                    serviceContext.getGuestPermissions());
140                    }
141    
142                    // Parent folder
143    
144                    if (parentFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
145                            dlFolderLocalService.updateLastPostDate(parentFolderId, now);
146                    }
147    
148                    // App helper
149    
150                    dlAppHelperLocalService.addFolder(
151                            userId, new LiferayFolder(dlFolder), serviceContext);
152    
153                    return dlFolder;
154            }
155    
156            /**
157             * @deprecated As of 6.2.0, replaced by more general {@link #addFolder(long,
158             *             long, long, boolean, long, String, String, boolean,
159             *             ServiceContext)}
160             */
161            @Override
162            public DLFolder addFolder(
163                            long userId, long groupId, long repositoryId, boolean mountPoint,
164                            long parentFolderId, String name, String description,
165                            ServiceContext serviceContext)
166                    throws PortalException, SystemException {
167    
168                    return addFolder(
169                            userId, groupId, repositoryId, mountPoint, parentFolderId, name,
170                            description, false, serviceContext);
171            }
172    
173            /**
174             * @deprecated As of 7.0.0, replaced by {@link #deleteAllByGroup(long)}
175             */
176            @Override
177            public void deleteAll(long groupId)
178                    throws PortalException, SystemException {
179    
180                    deleteAllByGroup(groupId);
181            }
182    
183            @Override
184            public void deleteAllByGroup(long groupId)
185                    throws PortalException, SystemException {
186    
187                    Group group = groupLocalService.getGroup(groupId);
188    
189                    List<DLFolder> dlFolders = dlFolderPersistence.findByGroupId(groupId);
190    
191                    for (DLFolder dlFolder : dlFolders) {
192                            dlFolderLocalService.deleteFolder(dlFolder);
193                    }
194    
195                    dlFileEntryLocalService.deleteFileEntries(
196                            groupId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
197    
198                    dlFileEntryTypeLocalService.deleteFileEntryTypes(groupId);
199    
200                    dlFileShortcutLocalService.deleteFileShortcuts(
201                            groupId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
202    
203                    try {
204                            DLStoreUtil.deleteDirectory(
205                                    group.getCompanyId(), groupId, StringPool.BLANK);
206                    }
207                    catch (NoSuchDirectoryException nsde) {
208                            if (_log.isDebugEnabled()) {
209                                    _log.debug(nsde.getMessage());
210                            }
211                    }
212            }
213    
214            @Override
215            public void deleteAllByRepository(long repositoryId)
216                    throws PortalException, SystemException {
217    
218                    Repository repository = repositoryLocalService.fetchRepository(
219                            repositoryId);
220    
221                    long groupId = repositoryId;
222    
223                    if (repository != null) {
224                            groupId = repository.getGroupId();
225                    }
226    
227                    Group group = groupLocalService.getGroup(groupId);
228    
229                    List<DLFolder> dlFolders = dlFolderPersistence.findByRepositoryIdList(
230                            repositoryId);
231    
232                    for (DLFolder dlFolder : dlFolders) {
233                            dlFolderLocalService.deleteFolder(dlFolder);
234                    }
235    
236                    if (repository != null) {
237                            dlFileEntryLocalService.deleteRepositoryFileEntries(
238                                    repository.getRepositoryId(), repository.getDlFolderId());
239                    }
240                    else {
241                            dlFileEntryLocalService.deleteFileEntries(
242                                    groupId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
243    
244                            dlFileShortcutLocalService.deleteFileShortcuts(
245                                    groupId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
246                    }
247    
248                    try {
249                            DLStoreUtil.deleteDirectory(
250                                    group.getCompanyId(), repositoryId, StringPool.BLANK);
251                    }
252                    catch (NoSuchDirectoryException nsde) {
253                            if (_log.isDebugEnabled()) {
254                                    _log.debug(nsde.getMessage());
255                            }
256                    }
257            }
258    
259            @Indexable(type = IndexableType.DELETE)
260            @Override
261            @SystemEvent(
262                    action = SystemEventConstants.ACTION_SKIP, send = false,
263                    type = SystemEventConstants.TYPE_DELETE)
264            public DLFolder deleteFolder(DLFolder dlFolder)
265                    throws PortalException, SystemException {
266    
267                    return deleteFolder(dlFolder, true);
268            }
269    
270            @Indexable(type = IndexableType.DELETE)
271            @Override
272            @SystemEvent(
273                    action = SystemEventConstants.ACTION_SKIP, send = false,
274                    type = SystemEventConstants.TYPE_DELETE)
275            public DLFolder deleteFolder(
276                            DLFolder dlFolder, boolean includeTrashedEntries)
277                    throws PortalException, SystemException {
278    
279                    // Folders
280    
281                    List<DLFolder> dlFolders = dlFolderPersistence.findByG_P(
282                            dlFolder.getGroupId(), dlFolder.getFolderId());
283    
284                    for (DLFolder curDLFolder : dlFolders) {
285                            if (includeTrashedEntries || !curDLFolder.isInTrashExplicitly()) {
286                                    dlFolderLocalService.deleteFolder(
287                                            curDLFolder, includeTrashedEntries);
288                            }
289                    }
290    
291                    // Resources
292    
293                    resourceLocalService.deleteResource(
294                            dlFolder.getCompanyId(), DLFolder.class.getName(),
295                            ResourceConstants.SCOPE_INDIVIDUAL, dlFolder.getFolderId());
296    
297                    // WebDAVProps
298    
299                    webDAVPropsLocalService.deleteWebDAVProps(
300                            DLFolder.class.getName(), dlFolder.getFolderId());
301    
302                    // File entries
303    
304                    dlFileEntryLocalService.deleteFileEntries(
305                            dlFolder.getGroupId(), dlFolder.getFolderId(),
306                            includeTrashedEntries);
307    
308                    // File entry types
309    
310                    List<Long> fileEntryTypeIds = new ArrayList<Long>();
311    
312                    for (DLFileEntryType dlFileEntryType :
313                                    dlFileEntryTypeLocalService.getDLFolderDLFileEntryTypes(
314                                            dlFolder.getFolderId())) {
315    
316                            fileEntryTypeIds.add(dlFileEntryType.getFileEntryTypeId());
317                    }
318    
319                    if (fileEntryTypeIds.isEmpty()) {
320                            fileEntryTypeIds.add(
321                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_ALL);
322                    }
323    
324                    dlFileEntryTypeLocalService.unsetFolderFileEntryTypes(
325                            dlFolder.getFolderId());
326    
327                    // File shortcuts
328    
329                    dlFileShortcutLocalService.deleteFileShortcuts(
330                            dlFolder.getGroupId(), dlFolder.getFolderId(),
331                            includeTrashedEntries);
332    
333                    // Expando
334    
335                    expandoRowLocalService.deleteRows(dlFolder.getFolderId());
336    
337                    // App helper
338    
339                    dlAppHelperLocalService.deleteFolder(new LiferayFolder(dlFolder));
340    
341                    // Folder
342    
343                    dlFolderPersistence.remove(dlFolder);
344    
345                    // Directory
346    
347                    try {
348                            if (includeTrashedEntries) {
349                                    DLStoreUtil.deleteDirectory(
350                                            dlFolder.getCompanyId(), dlFolder.getFolderId(),
351                                            StringPool.BLANK);
352                            }
353                    }
354                    catch (NoSuchDirectoryException nsde) {
355                            if (_log.isDebugEnabled()) {
356                                    _log.debug(nsde.getMessage());
357                            }
358                    }
359    
360                    // Workflow
361    
362                    for (long fileEntryTypeId : fileEntryTypeIds) {
363                            WorkflowDefinitionLink workflowDefinitionLink = null;
364    
365                            try {
366                                    workflowDefinitionLink =
367                                            workflowDefinitionLinkLocalService.
368                                                    getWorkflowDefinitionLink(
369                                                            dlFolder.getCompanyId(), dlFolder.getGroupId(),
370                                                            DLFolder.class.getName(), dlFolder.getFolderId(),
371                                                            fileEntryTypeId);
372                            }
373                            catch (NoSuchWorkflowDefinitionLinkException nswdle) {
374                                    continue;
375                            }
376    
377                            workflowDefinitionLinkLocalService.deleteWorkflowDefinitionLink(
378                                    workflowDefinitionLink);
379                    }
380    
381                    return dlFolder;
382            }
383    
384            @Indexable(type = IndexableType.DELETE)
385            @Override
386            public DLFolder deleteFolder(long folderId)
387                    throws PortalException, SystemException {
388    
389                    return dlFolderLocalService.deleteFolder(folderId, true);
390            }
391    
392            @Indexable(type = IndexableType.DELETE)
393            @Override
394            public DLFolder deleteFolder(long folderId, boolean includeTrashedEntries)
395                    throws PortalException, SystemException {
396    
397                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
398    
399                    return dlFolderLocalService.deleteFolder(
400                            dlFolder, includeTrashedEntries);
401            }
402    
403            @Indexable(type = IndexableType.DELETE)
404            @Override
405            public DLFolder deleteFolder(
406                            long userId, long folderId, boolean includeTrashedEntries)
407                    throws PortalException, SystemException {
408    
409                    boolean hasLock = hasFolderLock(userId, folderId);
410    
411                    Lock lock = null;
412    
413                    if (!hasLock) {
414    
415                            // Lock
416    
417                            lock = lockFolder(
418                                    userId, folderId, null, false,
419                                    DLFolderImpl.LOCK_EXPIRATION_TIME);
420                    }
421    
422                    try {
423                            return deleteFolder(folderId, includeTrashedEntries);
424                    }
425                    finally {
426                            if (!hasLock) {
427    
428                                    // Unlock
429    
430                                    unlockFolder(folderId, lock.getUuid());
431                            }
432                    }
433            }
434    
435            @Override
436            public DLFolder fetchFolder(long folderId) throws SystemException {
437                    return dlFolderPersistence.fetchByPrimaryKey(folderId);
438            }
439    
440            @Override
441            public DLFolder fetchFolder(long groupId, long parentFolderId, String name)
442                    throws SystemException {
443    
444                    return dlFolderPersistence.fetchByG_P_N(groupId, parentFolderId, name);
445            }
446    
447            @Override
448            public List<DLFolder> getCompanyFolders(long companyId, int start, int end)
449                    throws SystemException {
450    
451                    return dlFolderPersistence.findByCompanyId(companyId, start, end);
452            }
453    
454            @Override
455            public int getCompanyFoldersCount(long companyId) throws SystemException {
456                    return dlFolderPersistence.countByCompanyId(companyId);
457            }
458    
459            /**
460             * @deprecated As of 6.2.0, replaced by {@link
461             *             #getFileEntriesAndFileShortcuts(long, long, QueryDefinition)}
462             */
463            @Override
464            public List<Object> getFileEntriesAndFileShortcuts(
465                            long groupId, long folderId, int status, int start, int end)
466                    throws SystemException {
467    
468                    QueryDefinition queryDefinition = new QueryDefinition(
469                            status, start, end, null);
470    
471                    return getFileEntriesAndFileShortcuts(
472                            groupId, folderId, queryDefinition);
473            }
474    
475            @Override
476            public List<Object> getFileEntriesAndFileShortcuts(
477                            long groupId, long folderId, QueryDefinition queryDefinition)
478                    throws SystemException {
479    
480                    return dlFolderFinder.findFE_FS_ByG_F(
481                            groupId, folderId, queryDefinition);
482            }
483    
484            /**
485             * @deprecated As of 6.2.0, replaced by {@link
486             *             #getFileEntriesAndFileShortcutsCount(long, long,
487             *             QueryDefinition)}
488             */
489            @Override
490            public int getFileEntriesAndFileShortcutsCount(
491                            long groupId, long folderId, int status)
492                    throws SystemException {
493    
494                    QueryDefinition queryDefinition = new QueryDefinition(status);
495    
496                    return getFileEntriesAndFileShortcutsCount(
497                            groupId, folderId, queryDefinition);
498            }
499    
500            @Override
501            public int getFileEntriesAndFileShortcutsCount(
502                            long groupId, long folderId, QueryDefinition queryDefinition)
503                    throws SystemException {
504    
505                    return dlFolderFinder.countFE_FS_ByG_F(
506                            groupId, folderId, queryDefinition);
507            }
508    
509            @Override
510            public DLFolder getFolder(long folderId)
511                    throws PortalException, SystemException {
512    
513                    return dlFolderPersistence.findByPrimaryKey(folderId);
514            }
515    
516            @Override
517            public DLFolder getFolder(long groupId, long parentFolderId, String name)
518                    throws PortalException, SystemException {
519    
520                    return dlFolderPersistence.findByG_P_N(groupId, parentFolderId, name);
521            }
522    
523            @Override
524            public long getFolderId(long companyId, long folderId)
525                    throws SystemException {
526    
527                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
528    
529                            // Ensure folder exists and belongs to the proper company
530    
531                            DLFolder dlFolder = dlFolderPersistence.fetchByPrimaryKey(folderId);
532    
533                            if ((dlFolder == null) || (companyId != dlFolder.getCompanyId())) {
534                                    folderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
535                            }
536                    }
537    
538                    return folderId;
539            }
540    
541            @Override
542            public List<DLFolder> getFolders(long groupId, long parentFolderId)
543                    throws SystemException {
544    
545                    return getFolders(groupId, parentFolderId, true);
546            }
547    
548            @Override
549            public List<DLFolder> getFolders(
550                            long groupId, long parentFolderId, boolean includeMountfolders)
551                    throws SystemException {
552    
553                    if (includeMountfolders) {
554                            return dlFolderPersistence.findByG_P(groupId, parentFolderId);
555                    }
556                    else {
557                            return dlFolderPersistence.findByG_M_P_H(
558                                    groupId, false, parentFolderId, false);
559                    }
560            }
561    
562            @Override
563            public List<DLFolder> getFolders(
564                            long groupId, long parentFolderId, boolean includeMountfolders,
565                            int start, int end, OrderByComparator obc)
566                    throws SystemException {
567    
568                    if (includeMountfolders) {
569                            return dlFolderPersistence.findByG_P(
570                                    groupId, parentFolderId, start, end, obc);
571                    }
572                    else {
573                            return dlFolderPersistence.findByG_M_P_H(
574                                    groupId, false, parentFolderId, false, start, end, obc);
575                    }
576            }
577    
578            @Override
579            public List<DLFolder> getFolders(
580                            long groupId, long parentFolderId, int start, int end,
581                            OrderByComparator obc)
582                    throws SystemException {
583    
584                    return getFolders(groupId, parentFolderId, true, start, end, obc);
585            }
586    
587            /**
588             * @deprecated As of 6.2.0, replaced by {@link
589             *             #getFoldersAndFileEntriesAndFileShortcuts(long, long,
590             *             String[], boolean, QueryDefinition)}
591             */
592            @Override
593            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
594                            long groupId, long folderId, int status,
595                            boolean includeMountFolders, int start, int end,
596                            OrderByComparator obc)
597                    throws SystemException {
598    
599                    QueryDefinition queryDefinition = new QueryDefinition(
600                            status, start, end, obc);
601    
602                    return getFoldersAndFileEntriesAndFileShortcuts(
603                            groupId, folderId, null, includeMountFolders, queryDefinition);
604            }
605    
606            /**
607             * @deprecated As of 6.2.0, replaced by {@link
608             *             #getFoldersAndFileEntriesAndFileShortcutsCount(long, long,
609             *             String[], boolean, QueryDefinition)}
610             */
611            @Override
612            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
613                            long groupId, long folderId, int status, String[] mimeTypes,
614                            boolean includeMountFolders, int start, int end,
615                            OrderByComparator obc)
616                    throws SystemException {
617    
618                    QueryDefinition queryDefinition = new QueryDefinition(
619                            status, start, end, obc);
620    
621                    return getFoldersAndFileEntriesAndFileShortcuts(
622                            groupId, folderId, mimeTypes, includeMountFolders, queryDefinition);
623            }
624    
625            @Override
626            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
627                            long groupId, long folderId, String[] mimeTypes,
628                            boolean includeMountFolders, QueryDefinition queryDefinition)
629                    throws SystemException {
630    
631                    return dlFolderFinder.findF_FE_FS_ByG_F_M_M(
632                            groupId, folderId, mimeTypes, includeMountFolders, queryDefinition);
633            }
634    
635            /**
636             * @deprecated As of 6.2.0, replaced by {@link
637             *             #getFoldersAndFileEntriesAndFileShortcutsCount(long, long,
638             *             String[], boolean, QueryDefinition)}
639             */
640            @Override
641            public int getFoldersAndFileEntriesAndFileShortcutsCount(
642                            long groupId, long folderId, int status,
643                            boolean includeMountFolders)
644                    throws SystemException {
645    
646                    QueryDefinition queryDefinition = new QueryDefinition(status);
647    
648                    return getFoldersAndFileEntriesAndFileShortcutsCount(
649                            groupId, folderId, null, includeMountFolders, queryDefinition);
650            }
651    
652            /**
653             * @deprecated As of 6.2.0, replaced by {@link
654             *             #getFoldersAndFileEntriesAndFileShortcutsCount(long, long,
655             *             String[], boolean, QueryDefinition)}
656             */
657            @Override
658            public int getFoldersAndFileEntriesAndFileShortcutsCount(
659                            long groupId, long folderId, int status, String[] mimeTypes,
660                            boolean includeMountFolders)
661                    throws SystemException {
662    
663                    QueryDefinition queryDefinition = new QueryDefinition(status);
664    
665                    return getFoldersAndFileEntriesAndFileShortcutsCount(
666                            groupId, folderId, mimeTypes, includeMountFolders, queryDefinition);
667            }
668    
669            @Override
670            public int getFoldersAndFileEntriesAndFileShortcutsCount(
671                            long groupId, long folderId, String[] mimeTypes,
672                            boolean includeMountFolders, QueryDefinition queryDefinition)
673                    throws SystemException {
674    
675                    return dlFolderFinder.countF_FE_FS_ByG_F_M_M(
676                            groupId, folderId, mimeTypes, includeMountFolders, queryDefinition);
677            }
678    
679            @Override
680            public int getFoldersCount(long groupId, long parentFolderId)
681                    throws SystemException {
682    
683                    return getFoldersCount(groupId, parentFolderId, true);
684            }
685    
686            @Override
687            public int getFoldersCount(
688                            long groupId, long parentFolderId, boolean includeMountfolders)
689                    throws SystemException {
690    
691                    if (includeMountfolders) {
692                            return dlFolderPersistence.countByG_P(groupId, parentFolderId);
693                    }
694                    else {
695                            return dlFolderPersistence.countByG_M_P_H(
696                                    groupId, false, parentFolderId, false);
697                    }
698            }
699    
700            @Override
701            public int getFoldersCount(
702                            long groupId, long parentFolderId, int status,
703                            boolean includeMountfolders)
704                    throws SystemException {
705    
706                    if (includeMountfolders) {
707                            return dlFolderPersistence.countByG_P_H_S(
708                                    groupId, parentFolderId, false, status);
709                    }
710                    else {
711                            return dlFolderPersistence.countByG_M_P_H_S(
712                                    groupId, false, parentFolderId, false, status);
713                    }
714            }
715    
716            @Override
717            public DLFolder getMountFolder(long repositoryId)
718                    throws PortalException, SystemException {
719    
720                    return dlFolderPersistence.findByRepositoryId(repositoryId);
721            }
722    
723            @Override
724            public List<DLFolder> getMountFolders(
725                            long groupId, long parentFolderId, int start, int end,
726                            OrderByComparator obc)
727                    throws SystemException {
728    
729                    return dlFolderPersistence.findByG_M_P_H(
730                            groupId, true, parentFolderId, false, start, end, obc);
731            }
732    
733            @Override
734            public int getMountFoldersCount(long groupId, long parentFolderId)
735                    throws SystemException {
736    
737                    return dlFolderPersistence.countByG_M_P_H(
738                            groupId, true, parentFolderId, false);
739            }
740    
741            @Override
742            public List<DLFolder> getNoAssetFolders() throws SystemException {
743                    return dlFolderFinder.findF_ByNoAssets();
744            }
745    
746            @Override
747            public void getSubfolderIds(
748                            List<Long> folderIds, long groupId, long folderId)
749                    throws SystemException {
750    
751                    List<DLFolder> dlFolders = dlFolderPersistence.findByG_P(
752                            groupId, folderId);
753    
754                    for (DLFolder dlFolder : dlFolders) {
755                            folderIds.add(dlFolder.getFolderId());
756    
757                            getSubfolderIds(
758                                    folderIds, dlFolder.getGroupId(), dlFolder.getFolderId());
759                    }
760            }
761    
762            @Override
763            public boolean hasFolderLock(long userId, long folderId)
764                    throws SystemException {
765    
766                    return lockLocalService.hasLock(
767                            userId, DLFolder.class.getName(), folderId);
768            }
769    
770            @Override
771            public Lock lockFolder(long userId, long folderId)
772                    throws PortalException, SystemException {
773    
774                    return lockFolder(
775                            userId, folderId, null, false, DLFolderImpl.LOCK_EXPIRATION_TIME);
776            }
777    
778            @Override
779            public Lock lockFolder(
780                            long userId, long folderId, String owner, boolean inheritable,
781                            long expirationTime)
782                    throws PortalException, SystemException {
783    
784                    if ((expirationTime <= 0) ||
785                            (expirationTime > DLFolderImpl.LOCK_EXPIRATION_TIME)) {
786    
787                            expirationTime = DLFolderImpl.LOCK_EXPIRATION_TIME;
788                    }
789    
790                    return lockLocalService.lock(
791                            userId, DLFolder.class.getName(), folderId, owner, inheritable,
792                            expirationTime);
793            }
794    
795            @Indexable(type = IndexableType.REINDEX)
796            @Override
797            public DLFolder moveFolder(
798                            long userId, long folderId, long parentFolderId,
799                            ServiceContext serviceContext)
800                    throws PortalException, SystemException {
801    
802                    boolean hasLock = hasFolderLock(userId, folderId);
803    
804                    Lock lock = null;
805    
806                    if (!hasLock) {
807    
808                            // Lock
809    
810                            lock = lockFolder(userId, folderId);
811                    }
812    
813                    try {
814                            DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
815    
816                            parentFolderId = getParentFolderId(dlFolder, parentFolderId);
817    
818                            validateFolder(
819                                    dlFolder.getFolderId(), dlFolder.getGroupId(), parentFolderId,
820                                    dlFolder.getName());
821    
822                            dlFolder.setModifiedDate(serviceContext.getModifiedDate(null));
823                            dlFolder.setParentFolderId(parentFolderId);
824                            dlFolder.setTreePath(dlFolder.buildTreePath());
825                            dlFolder.setExpandoBridgeAttributes(serviceContext);
826    
827                            dlFolderPersistence.update(dlFolder);
828    
829                            dlAppHelperLocalService.moveFolder(new LiferayFolder(dlFolder));
830    
831                            return dlFolder;
832                    }
833                    finally {
834                            if (!hasLock) {
835    
836                                    // Unlock
837    
838                                    unlockFolder(folderId, lock.getUuid());
839                            }
840                    }
841            }
842    
843            @Override
844            public void rebuildTree(long companyId) throws SystemException {
845                    TreePathUtil.rebuildTree(
846                            companyId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID,
847                            new TreeModelFinder<DLFolder>() {
848    
849                                    @Override
850                                    public List<DLFolder> findTreeModels(
851                                                    long previousId, long companyId, long parentPrimaryKey,
852                                                    int size)
853                                            throws SystemException {
854    
855                                            return dlFolderPersistence.findByF_C_P_NotS(
856                                                    previousId, companyId, parentPrimaryKey,
857                                                    WorkflowConstants.STATUS_IN_TRASH, QueryUtil.ALL_POS,
858                                                    size, new FolderIdComparator());
859                                    }
860    
861                            }
862                    );
863            }
864    
865            @Override
866            public void unlockFolder(
867                            long groupId, long parentFolderId, String name, String lockUuid)
868                    throws PortalException, SystemException {
869    
870                    DLFolder dlFolder = getFolder(groupId, parentFolderId, name);
871    
872                    unlockFolder(dlFolder.getFolderId(), lockUuid);
873            }
874    
875            @Override
876            public void unlockFolder(long folderId, String lockUuid)
877                    throws PortalException, SystemException {
878    
879                    if (Validator.isNotNull(lockUuid)) {
880                            try {
881                                    Lock lock = lockLocalService.getLock(
882                                            DLFolder.class.getName(), folderId);
883    
884                                    if (!lockUuid.equals(lock.getUuid())) {
885                                            throw new InvalidLockException("UUIDs do not match");
886                                    }
887                            }
888                            catch (PortalException pe) {
889                                    if (pe instanceof ExpiredLockException ||
890                                            pe instanceof NoSuchLockException) {
891                                    }
892                                    else {
893                                            throw pe;
894                                    }
895                            }
896                    }
897    
898                    lockLocalService.unlock(DLFolder.class.getName(), folderId);
899            }
900    
901            @Indexable(type = IndexableType.REINDEX)
902            @Override
903            public DLFolder updateFolder(
904                            long folderId, long parentFolderId, String name, String description,
905                            long defaultFileEntryTypeId, List<Long> fileEntryTypeIds,
906                            boolean overrideFileEntryTypes, ServiceContext serviceContext)
907                    throws PortalException, SystemException {
908    
909                    boolean hasLock = hasFolderLock(serviceContext.getUserId(), folderId);
910    
911                    Lock lock = null;
912    
913                    if (!hasLock) {
914    
915                            // Lock
916    
917                            lock = lockFolder(
918                                    serviceContext.getUserId(), folderId, null, false,
919                                    DLFolderImpl.LOCK_EXPIRATION_TIME);
920                    }
921    
922                    try {
923    
924                            // File entry types
925    
926                            DLFolder dlFolder = null;
927    
928                            if (folderId > DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
929                                    dlFolder = dlFolderLocalService.updateFolderAndFileEntryTypes(
930                                            serviceContext.getUserId(), folderId, parentFolderId, name,
931                                            description, defaultFileEntryTypeId, fileEntryTypeIds,
932                                            overrideFileEntryTypes, serviceContext);
933    
934                                    dlFileEntryTypeLocalService.cascadeFileEntryTypes(
935                                            serviceContext.getUserId(), dlFolder);
936                            }
937    
938                            // Workflow definitions
939    
940                            List<ObjectValuePair<Long, String>> workflowDefinitionOVPs =
941                                    new ArrayList<ObjectValuePair<Long, String>>();
942    
943                            if (fileEntryTypeIds.isEmpty()) {
944                                    fileEntryTypeIds.add(
945                                            DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_ALL);
946                            }
947                            else {
948                                    workflowDefinitionOVPs.add(
949                                            new ObjectValuePair<Long, String>(
950                                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_ALL,
951                                                    StringPool.BLANK));
952                            }
953    
954                            for (long fileEntryTypeId : fileEntryTypeIds) {
955                                    String workflowDefinition = StringPool.BLANK;
956    
957                                    if (overrideFileEntryTypes ||
958                                            (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID)) {
959    
960                                            workflowDefinition = ParamUtil.getString(
961                                                    serviceContext, "workflowDefinition" + fileEntryTypeId);
962                                    }
963    
964                                    workflowDefinitionOVPs.add(
965                                            new ObjectValuePair<Long, String>(
966                                                    fileEntryTypeId, workflowDefinition));
967                            }
968    
969                            workflowDefinitionLinkLocalService.updateWorkflowDefinitionLinks(
970                                    serviceContext.getUserId(), serviceContext.getCompanyId(),
971                                    serviceContext.getScopeGroupId(), DLFolder.class.getName(),
972                                    folderId, workflowDefinitionOVPs);
973    
974                            return dlFolder;
975                    }
976                    finally {
977                            if (!hasLock) {
978    
979                                    // Unlock
980    
981                                    unlockFolder(folderId, lock.getUuid());
982                            }
983                    }
984            }
985    
986            @Indexable(type = IndexableType.REINDEX)
987            @Override
988            public DLFolder updateFolder(
989                            long folderId, String name, String description,
990                            long defaultFileEntryTypeId, List<Long> fileEntryTypeIds,
991                            boolean overrideFileEntryTypes, ServiceContext serviceContext)
992                    throws PortalException, SystemException {
993    
994                    long parentFolderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
995    
996                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
997                            DLFolder dlFolder = getDLFolder(folderId);
998    
999                            parentFolderId = dlFolder.getParentFolderId();
1000                    }
1001    
1002                    return updateFolder(
1003                            folderId, parentFolderId, name, description, defaultFileEntryTypeId,
1004                            fileEntryTypeIds, overrideFileEntryTypes, serviceContext);
1005            }
1006    
1007            @Override
1008            public DLFolder updateFolderAndFileEntryTypes(
1009                            long userId, long folderId, long parentFolderId, String name,
1010                            String description, long defaultFileEntryTypeId,
1011                            List<Long> fileEntryTypeIds, boolean overrideFileEntryTypes,
1012                            ServiceContext serviceContext)
1013                    throws PortalException, SystemException {
1014    
1015                    boolean hasLock = hasFolderLock(userId, folderId);
1016    
1017                    Lock lock = null;
1018    
1019                    if (!hasLock) {
1020    
1021                            // Lock
1022    
1023                            lock = lockFolder(
1024                                    userId, folderId, null, false,
1025                                    DLFolderImpl.LOCK_EXPIRATION_TIME);
1026                    }
1027    
1028                    try {
1029    
1030                            // Folder
1031    
1032                            if (!overrideFileEntryTypes) {
1033                                    fileEntryTypeIds = Collections.emptyList();
1034                            }
1035    
1036                            DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
1037    
1038                            parentFolderId = getParentFolderId(dlFolder, parentFolderId);
1039    
1040                            validateFolder(
1041                                    folderId, dlFolder.getGroupId(), parentFolderId, name);
1042    
1043                            dlFolder.setModifiedDate(serviceContext.getModifiedDate(null));
1044                            dlFolder.setParentFolderId(parentFolderId);
1045                            dlFolder.setTreePath(dlFolder.buildTreePath());
1046                            dlFolder.setName(name);
1047                            dlFolder.setDescription(description);
1048                            dlFolder.setExpandoBridgeAttributes(serviceContext);
1049                            dlFolder.setOverrideFileEntryTypes(overrideFileEntryTypes);
1050                            dlFolder.setDefaultFileEntryTypeId(defaultFileEntryTypeId);
1051    
1052                            dlFolderPersistence.update(dlFolder);
1053    
1054                            // File entry types
1055    
1056                            if (fileEntryTypeIds != null) {
1057                                    dlFileEntryTypeLocalService.updateFolderFileEntryTypes(
1058                                            dlFolder, fileEntryTypeIds, defaultFileEntryTypeId,
1059                                            serviceContext);
1060                            }
1061    
1062                            // App helper
1063    
1064                            dlAppHelperLocalService.updateFolder(
1065                                    userId, new LiferayFolder(dlFolder), serviceContext);
1066    
1067                            return dlFolder;
1068                    }
1069                    finally {
1070                            if (!hasLock) {
1071    
1072                                    // Unlock
1073    
1074                                    unlockFolder(folderId, lock.getUuid());
1075                            }
1076                    }
1077            }
1078    
1079            @BufferedIncrement(
1080                    configuration = "DLFolderEntry",
1081                    incrementClass = DateOverrideIncrement.class)
1082            @Override
1083            public void updateLastPostDate(long folderId, Date lastPostDate)
1084                    throws PortalException, SystemException {
1085    
1086                    if (ExportImportThreadLocal.isImportInProcess() ||
1087                            (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) ||
1088                            (lastPostDate == null)) {
1089    
1090                            return;
1091                    }
1092    
1093                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
1094    
1095                    if (lastPostDate.before(dlFolder.getLastPostDate())) {
1096                            return;
1097                    }
1098    
1099                    dlFolder.setLastPostDate(lastPostDate);
1100    
1101                    dlFolderPersistence.update(dlFolder);
1102            }
1103    
1104            @Override
1105            public DLFolder updateStatus(
1106                            long userId, long folderId, int status,
1107                            Map<String, Serializable> workflowContext,
1108                            ServiceContext serviceContext)
1109                    throws PortalException, SystemException {
1110    
1111                    // Folder
1112    
1113                    User user = userPersistence.findByPrimaryKey(userId);
1114    
1115                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
1116    
1117                    int oldStatus = dlFolder.getStatus();
1118    
1119                    dlFolder.setStatus(status);
1120                    dlFolder.setStatusByUserId(user.getUserId());
1121                    dlFolder.setStatusByUserName(user.getFullName());
1122                    dlFolder.setStatusDate(new Date());
1123    
1124                    dlFolderPersistence.update(dlFolder);
1125    
1126                    // Asset
1127    
1128                    if (status == WorkflowConstants.STATUS_APPROVED) {
1129                            assetEntryLocalService.updateVisible(
1130                                    DLFolder.class.getName(), dlFolder.getFolderId(), true);
1131                    }
1132                    else if (status == WorkflowConstants.STATUS_IN_TRASH) {
1133                            assetEntryLocalService.updateVisible(
1134                                    DLFolder.class.getName(), dlFolder.getFolderId(), false);
1135                    }
1136    
1137                    // Indexer
1138    
1139                    if (((status == WorkflowConstants.STATUS_APPROVED) ||
1140                             (status == WorkflowConstants.STATUS_IN_TRASH) ||
1141                             (oldStatus == WorkflowConstants.STATUS_IN_TRASH)) &&
1142                            ((serviceContext == null) || serviceContext.isIndexingEnabled())) {
1143    
1144                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1145                                    DLFolderConstants.getClassName());
1146    
1147                            indexer.reindex(dlFolder);
1148                    }
1149    
1150                    return dlFolder;
1151            }
1152    
1153            protected void addFolderResources(
1154                            DLFolder dlFolder, boolean addGroupPermissions,
1155                            boolean addGuestPermissions)
1156                    throws PortalException, SystemException {
1157    
1158                    resourceLocalService.addResources(
1159                            dlFolder.getCompanyId(), dlFolder.getGroupId(),
1160                            dlFolder.getUserId(), DLFolder.class.getName(),
1161                            dlFolder.getFolderId(), false, addGroupPermissions,
1162                            addGuestPermissions);
1163            }
1164    
1165            protected void addFolderResources(
1166                            DLFolder dlFolder, String[] groupPermissions,
1167                            String[] guestPermissions)
1168                    throws PortalException, SystemException {
1169    
1170                    resourceLocalService.addModelResources(
1171                            dlFolder.getCompanyId(), dlFolder.getGroupId(),
1172                            dlFolder.getUserId(), DLFolder.class.getName(),
1173                            dlFolder.getFolderId(), groupPermissions, guestPermissions);
1174            }
1175    
1176            protected void addFolderResources(
1177                            long folderId, boolean addGroupPermissions,
1178                            boolean addGuestPermissions)
1179                    throws PortalException, SystemException {
1180    
1181                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
1182    
1183                    addFolderResources(dlFolder, addGroupPermissions, addGuestPermissions);
1184            }
1185    
1186            protected void addFolderResources(
1187                            long folderId, String[] groupPermissions, String[] guestPermissions)
1188                    throws PortalException, SystemException {
1189    
1190                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
1191    
1192                    addFolderResources(dlFolder, groupPermissions, guestPermissions);
1193            }
1194    
1195            protected long getParentFolderId(DLFolder dlFolder, long parentFolderId)
1196                    throws PortalException, SystemException {
1197    
1198                    parentFolderId = getParentFolderId(
1199                            dlFolder.getGroupId(), dlFolder.getRepositoryId(), parentFolderId);
1200    
1201                    if (parentFolderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1202                            return parentFolderId;
1203                    }
1204    
1205                    if (dlFolder.getFolderId() == parentFolderId) {
1206                            throw new InvalidFolderException(
1207                                    String.format(
1208                                            "Cannot move folder %s into itself", parentFolderId));
1209                    }
1210    
1211                    List<Long> subfolderIds = new ArrayList<Long>();
1212    
1213                    getSubfolderIds(
1214                            subfolderIds, dlFolder.getGroupId(), dlFolder.getFolderId());
1215    
1216                    if (subfolderIds.contains(parentFolderId)) {
1217                            throw new InvalidFolderException(
1218                                    String.format(
1219                                            "Cannot move folder %s into one of its children",
1220                                            parentFolderId));
1221                    }
1222    
1223                    return parentFolderId;
1224            }
1225    
1226            protected long getParentFolderId(
1227                            long groupId, long repositoryId, long parentFolderId)
1228                    throws PortalException, SystemException {
1229    
1230                    if (parentFolderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1231                            return parentFolderId;
1232                    }
1233    
1234                    DLFolder parentDLFolder = dlFolderPersistence.findByPrimaryKey(
1235                            parentFolderId);
1236    
1237                    if (parentDLFolder.getGroupId() != groupId) {
1238                            throw new NoSuchFolderException(
1239                                    String.format(
1240                                            "No folder exists with the primary key %s in group %s",
1241                                            parentFolderId, groupId));
1242                    }
1243    
1244                    if ((parentDLFolder.getRepositoryId() != repositoryId) &&
1245                            (parentDLFolder.getRepositoryId() != groupId)) {
1246    
1247                            Repository repository = repositoryLocalService.getRepository(
1248                                    repositoryId);
1249    
1250                            if (repository.getGroupId() != parentDLFolder.getGroupId()) {
1251                                    throw new NoSuchFolderException(
1252                                            String.format(
1253                                                    "No folder exists with the primary key %s in " +
1254                                                            "repository %s",
1255                                                    parentFolderId, repositoryId));
1256                            }
1257                    }
1258    
1259                    return parentDLFolder.getFolderId();
1260            }
1261    
1262            protected void validateFolder(
1263                            long folderId, long groupId, long parentFolderId, String name)
1264                    throws PortalException, SystemException {
1265    
1266                    validateFolderName(name);
1267    
1268                    DLStoreUtil.validateDirectoryName(name);
1269    
1270                    try {
1271                            dlFileEntryLocalService.getFileEntry(groupId, parentFolderId, name);
1272    
1273                            throw new DuplicateFileException(name);
1274                    }
1275                    catch (NoSuchFileEntryException nsfee) {
1276                    }
1277    
1278                    DLFolder dlFolder = dlFolderPersistence.fetchByG_P_N(
1279                            groupId, parentFolderId, name);
1280    
1281                    if ((dlFolder != null) && (dlFolder.getFolderId() != folderId)) {
1282                            throw new DuplicateFolderNameException(name);
1283                    }
1284            }
1285    
1286            protected void validateFolder(
1287                            long groupId, long parentFolderId, String name)
1288                    throws PortalException, SystemException {
1289    
1290                    long folderId = 0;
1291    
1292                    validateFolder(folderId, groupId, parentFolderId, name);
1293            }
1294    
1295            protected void validateFolderName(String folderName)
1296                    throws PortalException {
1297    
1298                    if (folderName.contains(StringPool.SLASH)) {
1299                            throw new FolderNameException(folderName);
1300                    }
1301            }
1302    
1303            private static Log _log = LogFactoryUtil.getLog(
1304                    DLFolderLocalServiceImpl.class);
1305    
1306    }