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