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