001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.journal.service.impl;
016    
017    import com.liferay.portal.kernel.dao.orm.QueryDefinition;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.json.JSONFactoryUtil;
022    import com.liferay.portal.kernel.json.JSONObject;
023    import com.liferay.portal.kernel.search.Indexable;
024    import com.liferay.portal.kernel.search.IndexableType;
025    import com.liferay.portal.kernel.search.Indexer;
026    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
027    import com.liferay.portal.kernel.systemevent.SystemEvent;
028    import com.liferay.portal.kernel.util.ContentTypes;
029    import com.liferay.portal.kernel.util.OrderByComparator;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.kernel.util.TreeModelFinder;
032    import com.liferay.portal.kernel.util.TreePathUtil;
033    import com.liferay.portal.kernel.util.UnicodeProperties;
034    import com.liferay.portal.kernel.workflow.WorkflowConstants;
035    import com.liferay.portal.model.ResourceConstants;
036    import com.liferay.portal.model.SystemEventConstants;
037    import com.liferay.portal.model.TreeModel;
038    import com.liferay.portal.model.User;
039    import com.liferay.portal.service.ServiceContext;
040    import com.liferay.portal.util.PropsValues;
041    import com.liferay.portlet.asset.model.AssetEntry;
042    import com.liferay.portlet.asset.model.AssetLinkConstants;
043    import com.liferay.portlet.asset.util.AssetUtil;
044    import com.liferay.portlet.journal.DuplicateFolderNameException;
045    import com.liferay.portlet.journal.FolderNameException;
046    import com.liferay.portlet.journal.model.JournalArticle;
047    import com.liferay.portlet.journal.model.JournalFolder;
048    import com.liferay.portlet.journal.model.JournalFolderConstants;
049    import com.liferay.portlet.journal.service.base.JournalFolderLocalServiceBaseImpl;
050    import com.liferay.portlet.journal.util.comparator.FolderIdComparator;
051    import com.liferay.portlet.social.model.SocialActivityConstants;
052    import com.liferay.portlet.trash.model.TrashEntry;
053    import com.liferay.portlet.trash.model.TrashVersion;
054    import com.liferay.portlet.trash.util.TrashUtil;
055    
056    import java.util.ArrayList;
057    import java.util.Date;
058    import java.util.List;
059    
060    /**
061     * @author Juan Fern??ndez
062     */
063    public class JournalFolderLocalServiceImpl
064            extends JournalFolderLocalServiceBaseImpl {
065    
066            @Override
067            public JournalFolder addFolder(
068                            long userId, long groupId, long parentFolderId, String name,
069                            String description, ServiceContext serviceContext)
070                    throws PortalException, SystemException {
071    
072                    // Folder
073    
074                    User user = userPersistence.findByPrimaryKey(userId);
075                    parentFolderId = getParentFolderId(groupId, parentFolderId);
076                    Date now = new Date();
077    
078                    validateFolder(0, groupId, parentFolderId, name);
079    
080                    long folderId = counterLocalService.increment();
081    
082                    JournalFolder folder = journalFolderPersistence.create(folderId);
083    
084                    folder.setUuid(serviceContext.getUuid());
085                    folder.setGroupId(groupId);
086                    folder.setCompanyId(user.getCompanyId());
087                    folder.setUserId(user.getUserId());
088                    folder.setUserName(user.getFullName());
089                    folder.setCreateDate(serviceContext.getCreateDate(now));
090                    folder.setModifiedDate(serviceContext.getModifiedDate(now));
091                    folder.setParentFolderId(parentFolderId);
092                    folder.setTreePath(folder.buildTreePath());
093                    folder.setName(name);
094                    folder.setDescription(description);
095                    folder.setExpandoBridgeAttributes(serviceContext);
096    
097                    journalFolderPersistence.update(folder);
098    
099                    // Resources
100    
101                    resourceLocalService.addModelResources(folder, serviceContext);
102    
103                    // Asset
104    
105                    updateAsset(
106                            userId, folder, serviceContext.getAssetCategoryIds(),
107                            serviceContext.getAssetTagNames(),
108                            serviceContext.getAssetLinkEntryIds());
109    
110                    return folder;
111            }
112    
113            @Indexable(type = IndexableType.DELETE)
114            @Override
115            @SystemEvent(
116                    action = SystemEventConstants.ACTION_SKIP, send = false,
117                    type = SystemEventConstants.TYPE_DELETE)
118            public JournalFolder deleteFolder(JournalFolder folder)
119                    throws PortalException, SystemException {
120    
121                    return deleteFolder(folder, true);
122            }
123    
124            @Indexable(type = IndexableType.DELETE)
125            @Override
126            @SystemEvent(
127                    action = SystemEventConstants.ACTION_SKIP, send = false,
128                    type = SystemEventConstants.TYPE_DELETE)
129            public JournalFolder deleteFolder(
130                            JournalFolder folder, boolean includeTrashedEntries)
131                    throws PortalException, SystemException {
132    
133                    // Folders
134    
135                    List<JournalFolder> folders = journalFolderPersistence.findByG_P(
136                            folder.getGroupId(), folder.getFolderId());
137    
138                    for (JournalFolder curFolder : folders) {
139                            if (includeTrashedEntries || !curFolder.isInTrashExplicitly()) {
140                                    deleteFolder(curFolder, includeTrashedEntries);
141                            }
142                    }
143    
144                    // Folder
145    
146                    journalFolderPersistence.remove(folder);
147    
148                    // Resources
149    
150                    resourceLocalService.deleteResource(
151                            folder, ResourceConstants.SCOPE_INDIVIDUAL);
152    
153                    // Entries
154    
155                    journalArticleLocalService.deleteArticles(
156                            folder.getGroupId(), folder.getFolderId(), includeTrashedEntries);
157    
158                    // Asset
159    
160                    assetEntryLocalService.deleteEntry(
161                            JournalFolder.class.getName(), folder.getFolderId());
162    
163                    // Expando
164    
165                    expandoValueLocalService.deleteValues(
166                            JournalFolder.class.getName(), folder.getFolderId());
167    
168                    // Trash
169    
170                    trashEntryLocalService.deleteEntry(
171                            JournalFolder.class.getName(), folder.getFolderId());
172    
173                    return folder;
174            }
175    
176            @Indexable(type = IndexableType.DELETE)
177            @Override
178            public JournalFolder deleteFolder(long folderId)
179                    throws PortalException, SystemException {
180    
181                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
182                            folderId);
183    
184                    return journalFolderLocalService.deleteFolder(folder, true);
185            }
186    
187            @Indexable(type = IndexableType.DELETE)
188            @Override
189            public JournalFolder deleteFolder(
190                            long folderId, boolean includeTrashedEntries)
191                    throws PortalException, SystemException {
192    
193                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
194                            folderId);
195    
196                    return journalFolderLocalService.deleteFolder(
197                            folder, includeTrashedEntries);
198            }
199    
200            @Override
201            public void deleteFolders(long groupId)
202                    throws PortalException, SystemException {
203    
204                    List<JournalFolder> folders = journalFolderPersistence.findByGroupId(
205                            groupId);
206    
207                    for (JournalFolder folder : folders) {
208                            journalFolderLocalService.deleteFolder(folder);
209                    }
210            }
211    
212            @Override
213            public JournalFolder fetchFolder(long folderId) throws SystemException {
214                    return journalFolderPersistence.fetchByPrimaryKey(folderId);
215            }
216    
217            @Override
218            public JournalFolder fetchFolder(
219                            long groupId, long parentFolderId, String name)
220                    throws SystemException {
221    
222                    return journalFolderPersistence.fetchByG_P_N(
223                                    groupId, parentFolderId, name);
224            }
225    
226            @Override
227            public JournalFolder fetchFolder(long groupId, String name)
228                    throws SystemException {
229    
230                    return journalFolderPersistence.fetchByG_N(groupId, name);
231            }
232    
233            @Override
234            public List<JournalFolder> getCompanyFolders(
235                            long companyId, int start, int end)
236                    throws SystemException {
237    
238                    return journalFolderPersistence.findByCompanyId(companyId, start, end);
239            }
240    
241            @Override
242            public int getCompanyFoldersCount(long companyId) throws SystemException {
243                    return journalFolderPersistence.countByCompanyId(companyId);
244            }
245    
246            @Override
247            public JournalFolder getFolder(long folderId)
248                    throws PortalException, SystemException {
249    
250                    return journalFolderPersistence.findByPrimaryKey(folderId);
251            }
252    
253            @Override
254            public List<JournalFolder> getFolders(long groupId) throws SystemException {
255                    return journalFolderPersistence.findByGroupId(groupId);
256            }
257    
258            @Override
259            public List<JournalFolder> getFolders(long groupId, long parentFolderId)
260                    throws SystemException {
261    
262                    return getFolders(
263                            groupId, parentFolderId, WorkflowConstants.STATUS_APPROVED);
264            }
265    
266            @Override
267            public List<JournalFolder> getFolders(
268                            long groupId, long parentFolderId, int status)
269                    throws SystemException {
270    
271                    return journalFolderPersistence.findByG_P_S(
272                            groupId, parentFolderId, status);
273            }
274    
275            @Override
276            public List<JournalFolder> getFolders(
277                            long groupId, long parentFolderId, int start, int end)
278                    throws SystemException {
279    
280                    return getFolders(
281                            groupId, parentFolderId, WorkflowConstants.STATUS_APPROVED, start,
282                            end);
283            }
284    
285            @Override
286            public List<JournalFolder> getFolders(
287                            long groupId, long parentFolderId, int status, int start, int end)
288                    throws SystemException {
289    
290                    return journalFolderPersistence.findByG_P_S(
291                                    groupId, parentFolderId, status, start, end);
292            }
293    
294            @Override
295            public List<Object> getFoldersAndArticles(long groupId, long folderId)
296                    throws SystemException {
297    
298                    QueryDefinition queryDefinition = new QueryDefinition(
299                            WorkflowConstants.STATUS_ANY);
300    
301                    return journalFolderFinder.findF_A_ByG_F(
302                            groupId, folderId, queryDefinition);
303            }
304    
305            @Override
306            public List<Object> getFoldersAndArticles(
307                            long groupId, long folderId, int status)
308                    throws SystemException {
309    
310                    QueryDefinition queryDefinition = new QueryDefinition(status);
311    
312                    return journalFolderFinder.findF_A_ByG_F(
313                            groupId, folderId, queryDefinition);
314            }
315    
316            @Override
317            public List<Object> getFoldersAndArticles(
318                            long groupId, long folderId, int start, int end,
319                            OrderByComparator obc)
320                    throws SystemException {
321    
322                    QueryDefinition queryDefinition = new QueryDefinition(
323                            WorkflowConstants.STATUS_ANY, start, end, obc);
324    
325                    return journalFolderFinder.findF_A_ByG_F(
326                            groupId, folderId, queryDefinition);
327            }
328    
329            @Override
330            public int getFoldersAndArticlesCount(
331                            long groupId, List<Long> folderIds, int status)
332                    throws SystemException {
333    
334                    QueryDefinition queryDefinition = new QueryDefinition(status);
335    
336                    if (folderIds.size() <= PropsValues.SQL_DATA_MAX_PARAMETERS) {
337                            return journalArticleFinder.countByG_F(
338                                    groupId, folderIds, queryDefinition);
339                    }
340                    else {
341                            int start = 0;
342                            int end = PropsValues.SQL_DATA_MAX_PARAMETERS;
343    
344                            int articlesCount = journalArticleFinder.countByG_F(
345                                    groupId, folderIds.subList(start, end), queryDefinition);
346    
347                            folderIds.subList(start, end).clear();
348    
349                            articlesCount += getFoldersAndArticlesCount(
350                                    groupId, folderIds, status);
351    
352                            return articlesCount;
353                    }
354            }
355    
356            @Override
357            public int getFoldersAndArticlesCount(long groupId, long folderId)
358                    throws SystemException {
359    
360                    return journalFolderFinder.countF_A_ByG_F(
361                            groupId, folderId,
362                            new QueryDefinition(WorkflowConstants.STATUS_ANY));
363            }
364    
365            @Override
366            public int getFoldersAndArticlesCount(
367                            long groupId, long folderId, int status)
368                    throws SystemException {
369    
370                    return journalFolderFinder.countF_A_ByG_F(
371                            groupId, folderId, new QueryDefinition(status));
372            }
373    
374            @Override
375            public int getFoldersCount(long groupId, long parentFolderId)
376                    throws SystemException {
377    
378                    return getFoldersCount(
379                            groupId, parentFolderId, WorkflowConstants.STATUS_APPROVED);
380            }
381    
382            @Override
383            public int getFoldersCount(long groupId, long parentFolderId, int status)
384                    throws SystemException {
385    
386                    return journalFolderPersistence.countByG_P_S(
387                            groupId, parentFolderId, status);
388            }
389    
390            @Override
391            public List<JournalFolder> getNoAssetFolders() throws SystemException {
392                    return journalFolderFinder.findF_ByNoAssets();
393            }
394    
395            @Override
396            public void getSubfolderIds(
397                            List<Long> folderIds, long groupId, long folderId)
398                    throws SystemException {
399    
400                    List<JournalFolder> folders = journalFolderPersistence.findByG_P(
401                            groupId, folderId);
402    
403                    for (JournalFolder folder : folders) {
404                            folderIds.add(folder.getFolderId());
405    
406                            getSubfolderIds(
407                                    folderIds, folder.getGroupId(), folder.getFolderId());
408                    }
409            }
410    
411            @Indexable(type = IndexableType.REINDEX)
412            @Override
413            public JournalFolder moveFolder(
414                            long folderId, long parentFolderId, ServiceContext serviceContext)
415                    throws PortalException, SystemException {
416    
417                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
418                            folderId);
419    
420                    parentFolderId = getParentFolderId(folder, parentFolderId);
421    
422                    if (folder.getParentFolderId() == parentFolderId) {
423                            return folder;
424                    }
425    
426                    validateFolder(
427                            folder.getFolderId(), folder.getGroupId(), parentFolderId,
428                            folder.getName());
429    
430                    folder.setModifiedDate(serviceContext.getModifiedDate(null));
431                    folder.setParentFolderId(parentFolderId);
432                    folder.setTreePath(folder.buildTreePath());
433                    folder.setExpandoBridgeAttributes(serviceContext);
434    
435                    journalFolderPersistence.update(folder);
436    
437                    rebuildTree(
438                            folder.getCompanyId(), folderId, folder.getTreePath(), true);
439    
440                    return folder;
441            }
442    
443            @Override
444            public JournalFolder moveFolderFromTrash(
445                            long userId, long folderId, long parentFolderId,
446                            ServiceContext serviceContext)
447                    throws PortalException, SystemException {
448    
449                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
450                            folderId);
451    
452                    if (folder.isInTrashExplicitly()) {
453                            restoreFolderFromTrash(userId, folderId);
454                    }
455                    else {
456    
457                            // Folder
458    
459                            TrashEntry trashEntry = folder.getTrashEntry();
460    
461                            TrashVersion trashVersion =
462                                    trashVersionLocalService.fetchVersion(
463                                            trashEntry.getEntryId(), JournalFolder.class.getName(),
464                                            folderId);
465    
466                            int status = WorkflowConstants.STATUS_APPROVED;
467    
468                            if (trashVersion != null) {
469                                    status = trashVersion.getStatus();
470                            }
471    
472                            updateStatus(userId, folder, status);
473    
474                            // Trash
475    
476                            if (trashVersion != null) {
477                                    trashVersionLocalService.deleteTrashVersion(trashVersion);
478                            }
479    
480                            // Folders and articles
481    
482                            List<Object> foldersAndArticles =
483                                    journalFolderLocalService.getFoldersAndArticles(
484                                            folder.getGroupId(), folder.getFolderId(),
485                                            WorkflowConstants.STATUS_IN_TRASH);
486    
487                            restoreDependentsFromTrash(
488                                    foldersAndArticles, trashEntry.getEntryId());
489                    }
490    
491                    return journalFolderLocalService.moveFolder(
492                            folderId, parentFolderId, serviceContext);
493            }
494    
495            @Override
496            public JournalFolder moveFolderToTrash(long userId, long folderId)
497                    throws PortalException, SystemException {
498    
499                    // Folder
500    
501                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
502                            folderId);
503    
504                    String title = folder.getName();
505    
506                    folder = updateStatus(
507                            userId, folder, WorkflowConstants.STATUS_IN_TRASH);
508    
509                    // Trash
510    
511                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
512    
513                    typeSettingsProperties.put("title", folder.getName());
514    
515                    TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
516                            userId, folder.getGroupId(), JournalFolder.class.getName(),
517                            folder.getFolderId(), folder.getUuid(), null,
518                            WorkflowConstants.STATUS_APPROVED, null, typeSettingsProperties);
519    
520                    folder.setName(TrashUtil.getTrashTitle(trashEntry.getEntryId()));
521    
522                    journalFolderPersistence.update(folder);
523    
524                    // Folders and articles
525    
526                    List<Object> foldersAndArticles =
527                            journalFolderLocalService.getFoldersAndArticles(
528                                    folder.getGroupId(), folder.getFolderId());
529    
530                    moveDependentsToTrash(foldersAndArticles, trashEntry.getEntryId());
531    
532                    // Social
533    
534                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
535    
536                    extraDataJSONObject.put("title", title);
537    
538                    socialActivityLocalService.addActivity(
539                            userId, folder.getGroupId(), JournalFolder.class.getName(),
540                            folder.getFolderId(), SocialActivityConstants.TYPE_MOVE_TO_TRASH,
541                            extraDataJSONObject.toString(), 0);
542    
543                    return folder;
544            }
545    
546            @Override
547            public void rebuildTree(long companyId)
548                    throws PortalException, SystemException {
549    
550                    rebuildTree(
551                            companyId, JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID,
552                            StringPool.SLASH, false);
553            }
554    
555            @Override
556            public void rebuildTree(
557                            long companyId, long parentFolderId, String parentTreePath,
558                            final boolean reindex)
559                    throws PortalException, SystemException {
560    
561                    TreePathUtil.rebuildTree(
562                            companyId, parentFolderId, parentTreePath,
563                            new TreeModelFinder<JournalFolder>() {
564    
565                                    @Override
566                                    public List<JournalFolder> findTreeModels(
567                                                    long previousId, long companyId, long parentPrimaryKey,
568                                                    int size)
569                                            throws SystemException {
570    
571                                            return journalFolderPersistence.findByF_C_P_NotS(
572                                                    previousId, companyId, parentPrimaryKey,
573                                                    WorkflowConstants.STATUS_IN_TRASH, QueryUtil.ALL_POS,
574                                                    size, new FolderIdComparator());
575                                    }
576    
577                                    @Override
578                                    public void rebuildDependentModelsTreePaths(
579                                                    long parentPrimaryKey, String treePath)
580                                            throws PortalException, SystemException {
581    
582                                            journalArticleLocalService.setTreePaths(
583                                                    parentPrimaryKey, treePath, false);
584                            }
585    
586                                    @Override
587                                    public void reindexTreeModels(List<TreeModel> treeModels)
588                                            throws PortalException {
589    
590                                            if (!reindex) {
591                                                    return;
592                                            }
593    
594                                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
595                                                    JournalFolder.class);
596    
597                                            for (TreeModel treeModel : treeModels) {
598                                                    indexer.reindex(treeModel);
599                                            }
600                                    }
601                            }
602                    );
603            }
604    
605            @Override
606            public void restoreFolderFromTrash(long userId, long folderId)
607                    throws PortalException, SystemException {
608    
609                    // Folder
610    
611                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
612                            folderId);
613    
614                    folder.setName(TrashUtil.getOriginalTitle(folder.getName()));
615    
616                    journalFolderPersistence.update(folder);
617    
618                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
619                            JournalFolder.class.getName(), folderId);
620    
621                    updateStatus(userId, folder, trashEntry.getStatus());
622    
623                    // Folders and articles
624    
625                    List<Object> foldersAndArticles =
626                            journalFolderLocalService.getFoldersAndArticles(
627                                    folder.getGroupId(), folder.getFolderId(),
628                                    WorkflowConstants.STATUS_IN_TRASH);
629    
630                    restoreDependentsFromTrash(foldersAndArticles, trashEntry.getEntryId());
631    
632                    // Trash
633    
634                    trashEntryLocalService.deleteEntry(
635                            JournalFolder.class.getName(), folder.getFolderId());
636    
637                    // Social
638    
639                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
640    
641                    extraDataJSONObject.put("title", folder.getName());
642    
643                    socialActivityLocalService.addActivity(
644                            userId, folder.getGroupId(), JournalFolder.class.getName(),
645                            folder.getFolderId(),
646                            SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
647                            extraDataJSONObject.toString(), 0);
648            }
649    
650            @Override
651            public void updateAsset(
652                            long userId, JournalFolder folder, long[] assetCategoryIds,
653                            String[] assetTagNames, long[] assetLinkEntryIds)
654                    throws PortalException, SystemException {
655    
656                    AssetEntry assetEntry = assetEntryLocalService.updateEntry(
657                            userId, folder.getGroupId(), folder.getCreateDate(),
658                            folder.getModifiedDate(), JournalFolder.class.getName(),
659                            folder.getFolderId(), folder.getUuid(), 0, assetCategoryIds,
660                            assetTagNames, true, null, null, null, ContentTypes.TEXT_PLAIN,
661                            folder.getName(), folder.getDescription(), null, null, null, 0, 0,
662                            null, false);
663    
664                    assetLinkLocalService.updateLinks(
665                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
666                            AssetLinkConstants.TYPE_RELATED);
667            }
668    
669            @Indexable(type = IndexableType.REINDEX)
670            @Override
671            public JournalFolder updateFolder(
672                            long userId, long folderId, long parentFolderId, String name,
673                            String description, boolean mergeWithParentFolder,
674                            ServiceContext serviceContext)
675                    throws PortalException, SystemException {
676    
677                    // Merge folders
678    
679                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
680                            folderId);
681    
682                    parentFolderId = getParentFolderId(folder, parentFolderId);
683    
684                    if (mergeWithParentFolder && (folderId != parentFolderId)) {
685                            mergeFolders(folder, parentFolderId);
686    
687                            return folder;
688                    }
689    
690                    // Folder
691    
692                    validateFolder(folderId, folder.getGroupId(), parentFolderId, name);
693    
694                    long oldParentFolderId = folder.getParentFolderId();
695    
696                    if (oldParentFolderId != parentFolderId) {
697                            folder.setParentFolderId(parentFolderId);
698                            folder.setTreePath(folder.buildTreePath());
699                    }
700    
701                    folder.setModifiedDate(serviceContext.getModifiedDate(null));
702                    folder.setName(name);
703                    folder.setDescription(description);
704                    folder.setExpandoBridgeAttributes(serviceContext);
705    
706                    journalFolderPersistence.update(folder);
707    
708                    // Asset
709    
710                    updateAsset(
711                            userId, folder, serviceContext.getAssetCategoryIds(),
712                            serviceContext.getAssetTagNames(),
713                            serviceContext.getAssetLinkEntryIds());
714    
715                    if (oldParentFolderId != parentFolderId) {
716                            rebuildTree(
717                                    folder.getCompanyId(), folderId, folder.getTreePath(), true);
718                    }
719    
720                    return folder;
721            }
722    
723            @Override
724            public JournalFolder updateStatus(
725                            long userId, JournalFolder folder, int status)
726                    throws PortalException, SystemException {
727    
728                    // Folder
729    
730                    User user = userPersistence.findByPrimaryKey(userId);
731    
732                    folder.setStatus(status);
733                    folder.setStatusByUserId(userId);
734                    folder.setStatusByUserName(user.getFullName());
735                    folder.setStatusDate(new Date());
736    
737                    journalFolderPersistence.update(folder);
738    
739                    // Asset
740    
741                    if (status == WorkflowConstants.STATUS_APPROVED) {
742                            assetEntryLocalService.updateVisible(
743                                    JournalFolder.class.getName(), folder.getFolderId(), true);
744                    }
745                    else if (status == WorkflowConstants.STATUS_IN_TRASH) {
746                            assetEntryLocalService.updateVisible(
747                                    JournalFolder.class.getName(), folder.getFolderId(), false);
748                    }
749    
750                    // Index
751    
752                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
753                            JournalFolder.class);
754    
755                    indexer.reindex(folder);
756    
757                    return folder;
758            }
759    
760            protected long getParentFolderId(JournalFolder folder, long parentFolderId)
761                    throws SystemException {
762    
763                    if (parentFolderId == JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
764                            return parentFolderId;
765                    }
766    
767                    if (folder.getFolderId() == parentFolderId) {
768                            return folder.getParentFolderId();
769                    }
770    
771                    JournalFolder parentFolder = journalFolderPersistence.fetchByPrimaryKey(
772                            parentFolderId);
773    
774                    if ((parentFolder == null) ||
775                            (folder.getGroupId() != parentFolder.getGroupId())) {
776    
777                            return folder.getParentFolderId();
778                    }
779    
780                    List<Long> subfolderIds = new ArrayList<Long>();
781    
782                    getSubfolderIds(
783                            subfolderIds, folder.getGroupId(), folder.getFolderId());
784    
785                    if (subfolderIds.contains(parentFolderId)) {
786                            return folder.getParentFolderId();
787                    }
788    
789                    return parentFolderId;
790            }
791    
792            protected long getParentFolderId(long groupId, long parentFolderId)
793                    throws SystemException {
794    
795                    if (parentFolderId != JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
796                            JournalFolder parentFolder =
797                                    journalFolderPersistence.fetchByPrimaryKey(parentFolderId);
798    
799                            if ((parentFolder == null) ||
800                                    (groupId != parentFolder.getGroupId())) {
801    
802                                    parentFolderId =
803                                            JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID;
804                            }
805                    }
806    
807                    return parentFolderId;
808            }
809    
810            protected void mergeFolders(JournalFolder fromFolder, long toFolderId)
811                    throws PortalException, SystemException {
812    
813                    List<JournalFolder> folders = journalFolderPersistence.findByG_P(
814                            fromFolder.getGroupId(), fromFolder.getFolderId());
815    
816                    for (JournalFolder folder : folders) {
817                            mergeFolders(folder, toFolderId);
818                    }
819    
820                    List<JournalArticle> articles = journalArticlePersistence.findByG_F(
821                            fromFolder.getGroupId(), fromFolder.getFolderId());
822    
823                    for (JournalArticle article : articles) {
824                            article.setFolderId(toFolderId);
825                            article.setTreePath(article.buildTreePath());
826    
827                            journalArticlePersistence.update(article);
828    
829                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
830                                    JournalArticle.class);
831    
832                            indexer.reindex(article);
833                    }
834    
835                    journalFolderLocalService.deleteFolder(fromFolder);
836            }
837    
838            protected void moveDependentsToTrash(
839                            List<Object> foldersAndArticles, long trashEntryId)
840                    throws PortalException, SystemException {
841    
842                    for (Object object : foldersAndArticles) {
843                            if (object instanceof JournalArticle) {
844    
845                                    // Article
846    
847                                    JournalArticle article = (JournalArticle)object;
848    
849                                    if (article.getStatus() == WorkflowConstants.STATUS_IN_TRASH) {
850                                            continue;
851                                    }
852    
853                                    // Articles
854    
855                                    List<JournalArticle> articles =
856                                            journalArticlePersistence.findByG_A(
857                                                    article.getGroupId(), article.getArticleId());
858    
859                                    for (JournalArticle curArticle : articles) {
860    
861                                            // Article
862    
863                                            int curArticleOldStatus = curArticle.getStatus();
864    
865                                            curArticle.setStatus(WorkflowConstants.STATUS_IN_TRASH);
866    
867                                            journalArticlePersistence.update(curArticle);
868    
869                                            // Trash
870    
871                                            int status = curArticleOldStatus;
872    
873                                            if (curArticleOldStatus ==
874                                                            WorkflowConstants.STATUS_PENDING) {
875    
876                                                    status = WorkflowConstants.STATUS_DRAFT;
877                                            }
878    
879                                            if (curArticleOldStatus !=
880                                                            WorkflowConstants.STATUS_APPROVED) {
881    
882                                                    trashVersionLocalService.addTrashVersion(
883                                                            trashEntryId, JournalArticle.class.getName(),
884                                                            curArticle.getId(), status, null);
885                                            }
886    
887                                            // Workflow
888    
889                                            if (curArticleOldStatus ==
890                                                            WorkflowConstants.STATUS_PENDING) {
891    
892                                                    workflowInstanceLinkLocalService.
893                                                            deleteWorkflowInstanceLink(
894                                                                    curArticle.getCompanyId(),
895                                                                    curArticle.getGroupId(),
896                                                                    JournalArticle.class.getName(),
897                                                                    curArticle.getId());
898                                            }
899                                    }
900    
901                                    // Asset
902    
903                                    assetEntryLocalService.updateVisible(
904                                            JournalArticle.class.getName(),
905                                            article.getResourcePrimKey(), false);
906    
907                                    // Indexer
908    
909                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
910                                            JournalArticle.class);
911    
912                                    indexer.reindex(article);
913                            }
914                            else if (object instanceof JournalFolder) {
915    
916                                    // Folder
917    
918                                    JournalFolder folder = (JournalFolder)object;
919    
920                                    if (folder.isInTrashExplicitly()) {
921                                            continue;
922                                    }
923    
924                                    int oldStatus = folder.getStatus();
925    
926                                    folder.setStatus(WorkflowConstants.STATUS_IN_TRASH);
927    
928                                    journalFolderPersistence.update(folder);
929    
930                                    // Trash
931    
932                                    if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
933                                            trashVersionLocalService.addTrashVersion(
934                                                    trashEntryId, JournalFolder.class.getName(),
935                                                    folder.getFolderId(), oldStatus, null);
936                                    }
937    
938                                    // Folders and articles
939    
940                                    List<Object> curFoldersAndArticles = getFoldersAndArticles(
941                                            folder.getGroupId(), folder.getFolderId());
942    
943                                    moveDependentsToTrash(curFoldersAndArticles, trashEntryId);
944    
945                                    // Asset
946    
947                                    assetEntryLocalService.updateVisible(
948                                            JournalFolder.class.getName(), folder.getFolderId(), false);
949    
950                                    // Index
951    
952                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
953                                            JournalFolder.class);
954    
955                                    indexer.reindex(folder);
956                            }
957                    }
958            }
959    
960            protected void restoreDependentsFromTrash(
961                            List<Object> foldersAndArticles, long trashEntryId)
962                    throws PortalException, SystemException {
963    
964                    for (Object object : foldersAndArticles) {
965                            if (object instanceof JournalArticle) {
966    
967                                    // Article
968    
969                                    JournalArticle article = (JournalArticle)object;
970    
971                                    TrashEntry trashEntry = trashEntryLocalService.fetchEntry(
972                                            JournalArticle.class.getName(),
973                                            article.getResourcePrimKey());
974    
975                                    if (trashEntry != null) {
976                                            continue;
977                                    }
978    
979                                    TrashVersion trashVersion =
980                                            trashVersionLocalService.fetchVersion(
981                                                    trashEntryId, JournalArticle.class.getName(),
982                                                    article.getId());
983    
984                                    int oldStatus = WorkflowConstants.STATUS_APPROVED;
985    
986                                    if (trashVersion != null) {
987                                            oldStatus = trashVersion.getStatus();
988                                    }
989    
990                                    // Articles
991    
992                                    List<JournalArticle> articles =
993                                            journalArticlePersistence.findByG_A(
994                                                    article.getGroupId(), article.getArticleId());
995    
996                                    for (JournalArticle curArticle : articles) {
997    
998                                            // Article
999    
1000                                            trashVersion =
1001                                                    trashVersionLocalService.fetchVersion(
1002                                                            trashEntryId, JournalArticle.class.getName(),
1003                                                            curArticle.getId());
1004    
1005                                            int curArticleOldStatus = WorkflowConstants.STATUS_APPROVED;
1006    
1007                                            if (trashVersion != null) {
1008                                                    curArticleOldStatus = trashVersion.getStatus();
1009                                            }
1010    
1011                                            curArticle.setStatus(curArticleOldStatus);
1012    
1013                                            journalArticlePersistence.update(curArticle);
1014    
1015                                            // Trash
1016    
1017                                            if (trashVersion != null) {
1018                                                    trashVersionLocalService.deleteTrashVersion(
1019                                                            trashVersion);
1020                                            }
1021                                    }
1022    
1023                                    // Asset
1024    
1025                                    if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
1026                                            assetEntryLocalService.updateVisible(
1027                                                    JournalArticle.class.getName(),
1028                                                    article.getResourcePrimKey(), true);
1029                                    }
1030    
1031                                    // Indexer
1032    
1033                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1034                                            JournalArticle.class);
1035    
1036                                    indexer.reindex(article);
1037                            }
1038                            else if (object instanceof JournalFolder) {
1039    
1040                                    // Folder
1041    
1042                                    JournalFolder folder = (JournalFolder)object;
1043    
1044                                    TrashEntry trashEntry = trashEntryLocalService.fetchEntry(
1045                                            JournalFolder.class.getName(), folder.getFolderId());
1046    
1047                                    if (trashEntry != null) {
1048                                            continue;
1049                                    }
1050    
1051                                    TrashVersion trashVersion =
1052                                            trashVersionLocalService.fetchVersion(
1053                                                    trashEntryId, JournalFolder.class.getName(),
1054                                                    folder.getFolderId());
1055    
1056                                    int oldStatus = WorkflowConstants.STATUS_APPROVED;
1057    
1058                                    if (trashVersion != null) {
1059                                            oldStatus = trashVersion.getStatus();
1060                                    }
1061    
1062                                    folder.setStatus(oldStatus);
1063    
1064                                    journalFolderPersistence.update(folder);
1065    
1066                                    // Folders and articles
1067    
1068                                    List<Object> curFoldersAndArticles = getFoldersAndArticles(
1069                                            folder.getGroupId(), folder.getFolderId(),
1070                                            WorkflowConstants.STATUS_IN_TRASH);
1071    
1072                                    restoreDependentsFromTrash(curFoldersAndArticles, trashEntryId);
1073    
1074                                    // Trash
1075    
1076                                    if (trashVersion != null) {
1077                                            trashVersionLocalService.deleteTrashVersion(trashVersion);
1078                                    }
1079    
1080                                    // Asset
1081    
1082                                    assetEntryLocalService.updateVisible(
1083                                            JournalFolder.class.getName(), folder.getFolderId(), true);
1084    
1085                                    // Index
1086    
1087                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1088                                            JournalFolder.class);
1089    
1090                                    indexer.reindex(folder);
1091                            }
1092                    }
1093            }
1094    
1095            protected void validateFolder(
1096                            long folderId, long groupId, long parentFolderId, String name)
1097                    throws PortalException, SystemException {
1098    
1099                    validateFolderName(name);
1100    
1101                    JournalFolder folder = journalFolderPersistence.fetchByG_P_N(
1102                            groupId, parentFolderId, name);
1103    
1104                    if ((folder != null) && (folder.getFolderId() != folderId)) {
1105                            throw new DuplicateFolderNameException(name);
1106                    }
1107            }
1108    
1109            protected void validateFolderName(String name) throws PortalException {
1110                    if (!AssetUtil.isValidWord(name)) {
1111                            throw new FolderNameException();
1112                    }
1113    
1114                    if (name.contains("\\\\") || name.contains("//")) {
1115                            throw new FolderNameException();
1116                    }
1117            }
1118    
1119    }