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