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