001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.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.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.ArrayUtil;
028    import com.liferay.portal.kernel.util.ContentTypes;
029    import com.liferay.portal.kernel.util.ObjectValuePair;
030    import com.liferay.portal.kernel.util.OrderByComparator;
031    import com.liferay.portal.kernel.util.ParamUtil;
032    import com.liferay.portal.kernel.util.SetUtil;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.TreeModelTasksAdapter;
035    import com.liferay.portal.kernel.util.TreePathUtil;
036    import com.liferay.portal.kernel.util.UnicodeProperties;
037    import com.liferay.portal.kernel.workflow.WorkflowConstants;
038    import com.liferay.portal.model.ResourceConstants;
039    import com.liferay.portal.model.SystemEventConstants;
040    import com.liferay.portal.model.TreeModel;
041    import com.liferay.portal.model.User;
042    import com.liferay.portal.model.WorkflowDefinitionLink;
043    import com.liferay.portal.service.ServiceContext;
044    import com.liferay.portal.util.PortalUtil;
045    import com.liferay.portal.util.PropsValues;
046    import com.liferay.portlet.asset.model.AssetEntry;
047    import com.liferay.portlet.asset.model.AssetLinkConstants;
048    import com.liferay.portlet.asset.util.AssetUtil;
049    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
050    import com.liferay.portlet.journal.DuplicateFolderNameException;
051    import com.liferay.portlet.journal.FolderNameException;
052    import com.liferay.portlet.journal.InvalidDDMStructureException;
053    import com.liferay.portlet.journal.NoSuchFolderException;
054    import com.liferay.portlet.journal.model.JournalArticle;
055    import com.liferay.portlet.journal.model.JournalArticleConstants;
056    import com.liferay.portlet.journal.model.JournalFolder;
057    import com.liferay.portlet.journal.model.JournalFolderConstants;
058    import com.liferay.portlet.journal.service.base.JournalFolderLocalServiceBaseImpl;
059    import com.liferay.portlet.journal.util.comparator.FolderIdComparator;
060    import com.liferay.portlet.social.model.SocialActivityConstants;
061    import com.liferay.portlet.trash.model.TrashEntry;
062    import com.liferay.portlet.trash.model.TrashVersion;
063    import com.liferay.portlet.trash.util.TrashUtil;
064    
065    import java.util.ArrayList;
066    import java.util.Date;
067    import java.util.HashSet;
068    import java.util.List;
069    import java.util.Set;
070    
071    /**
072     * @author Juan Fern??ndez
073     */
074    public class JournalFolderLocalServiceImpl
075            extends JournalFolderLocalServiceBaseImpl {
076    
077            @Override
078            public JournalFolder addFolder(
079                            long userId, long groupId, long parentFolderId, String name,
080                            String description, ServiceContext serviceContext)
081                    throws PortalException {
082    
083                    // Folder
084    
085                    User user = userPersistence.findByPrimaryKey(userId);
086                    parentFolderId = getParentFolderId(groupId, parentFolderId);
087                    Date now = new Date();
088    
089                    validateFolder(0, groupId, parentFolderId, name);
090    
091                    long folderId = counterLocalService.increment();
092    
093                    JournalFolder folder = journalFolderPersistence.create(folderId);
094    
095                    folder.setUuid(serviceContext.getUuid());
096                    folder.setGroupId(groupId);
097                    folder.setCompanyId(user.getCompanyId());
098                    folder.setUserId(user.getUserId());
099                    folder.setUserName(user.getFullName());
100                    folder.setCreateDate(serviceContext.getCreateDate(now));
101                    folder.setModifiedDate(serviceContext.getModifiedDate(now));
102                    folder.setParentFolderId(parentFolderId);
103                    folder.setTreePath(folder.buildTreePath());
104                    folder.setName(name);
105                    folder.setDescription(description);
106                    folder.setExpandoBridgeAttributes(serviceContext);
107    
108                    journalFolderPersistence.update(folder);
109    
110                    // Resources
111    
112                    resourceLocalService.addModelResources(folder, serviceContext);
113    
114                    // Asset
115    
116                    updateAsset(
117                            userId, folder, serviceContext.getAssetCategoryIds(),
118                            serviceContext.getAssetTagNames(),
119                            serviceContext.getAssetLinkEntryIds());
120    
121                    return folder;
122            }
123    
124            @Indexable(type = IndexableType.DELETE)
125            @Override
126            @SystemEvent(
127                    action = SystemEventConstants.ACTION_SKIP,
128                    type = SystemEventConstants.TYPE_DELETE)
129            public JournalFolder deleteFolder(JournalFolder folder)
130                    throws PortalException {
131    
132                    return deleteFolder(folder, true);
133            }
134    
135            @Indexable(type = IndexableType.DELETE)
136            @Override
137            @SystemEvent(
138                    action = SystemEventConstants.ACTION_SKIP,
139                    type = SystemEventConstants.TYPE_DELETE)
140            public JournalFolder deleteFolder(
141                            JournalFolder folder, boolean includeTrashedEntries)
142                    throws PortalException {
143    
144                    // Folders
145    
146                    List<JournalFolder> folders = journalFolderPersistence.findByG_P(
147                            folder.getGroupId(), folder.getFolderId());
148    
149                    for (JournalFolder curFolder : folders) {
150                            if (includeTrashedEntries || !curFolder.isInTrashExplicitly()) {
151                                    journalFolderLocalService.deleteFolder(
152                                            curFolder, includeTrashedEntries);
153                            }
154                    }
155    
156                    // Folder
157    
158                    Set<Long> ddmStructureIds = getDDMStructureIds(
159                            journalFolderPersistence.getDDMStructures(folder.getFolderId()));
160    
161                    if (ddmStructureIds.isEmpty()) {
162                            ddmStructureIds.add(JournalArticleConstants.DDM_STRUCTURE_ID_ALL);
163                    }
164    
165                    journalFolderPersistence.remove(folder);
166    
167                    // Resources
168    
169                    resourceLocalService.deleteResource(
170                            folder, ResourceConstants.SCOPE_INDIVIDUAL);
171    
172                    // Entries
173    
174                    journalArticleLocalService.deleteArticles(
175                            folder.getGroupId(), folder.getFolderId(), includeTrashedEntries);
176    
177                    // Asset
178    
179                    assetEntryLocalService.deleteEntry(
180                            JournalFolder.class.getName(), folder.getFolderId());
181    
182                    // Expando
183    
184                    expandoValueLocalService.deleteValues(
185                            JournalFolder.class.getName(), folder.getFolderId());
186    
187                    // Trash
188    
189                    if (folder.isInTrashExplicitly()) {
190                            trashEntryLocalService.deleteEntry(
191                                    JournalFolder.class.getName(), folder.getFolderId());
192                    }
193                    else {
194                            trashVersionLocalService.deleteTrashVersion(
195                                    JournalFolder.class.getName(), folder.getFolderId());
196                    }
197    
198                    // Workflow
199    
200                    for (long ddmStructureId : ddmStructureIds) {
201                            WorkflowDefinitionLink workflowDefinitionLink =
202                                    workflowDefinitionLinkLocalService.fetchWorkflowDefinitionLink(
203                                            folder.getCompanyId(), folder.getGroupId(),
204                                            JournalFolder.class.getName(), folder.getFolderId(),
205                                            ddmStructureId);
206    
207                            if (workflowDefinitionLink != null) {
208                                    workflowDefinitionLinkLocalService.deleteWorkflowDefinitionLink(
209                                            workflowDefinitionLink);
210                            }
211                    }
212    
213                    return folder;
214            }
215    
216            @Indexable(type = IndexableType.DELETE)
217            @Override
218            public JournalFolder deleteFolder(long folderId) throws PortalException {
219                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
220                            folderId);
221    
222                    return journalFolderLocalService.deleteFolder(folder, true);
223            }
224    
225            @Indexable(type = IndexableType.DELETE)
226            @Override
227            public JournalFolder deleteFolder(
228                            long folderId, boolean includeTrashedEntries)
229                    throws PortalException {
230    
231                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
232                            folderId);
233    
234                    return journalFolderLocalService.deleteFolder(
235                            folder, includeTrashedEntries);
236            }
237    
238            @Override
239            public void deleteFolders(long groupId) throws PortalException {
240                    List<JournalFolder> folders = journalFolderPersistence.findByGroupId(
241                            groupId);
242    
243                    for (JournalFolder folder : folders) {
244                            journalFolderLocalService.deleteFolder(folder);
245                    }
246            }
247    
248            @Override
249            public JournalFolder fetchFolder(long folderId) {
250                    return journalFolderPersistence.fetchByPrimaryKey(folderId);
251            }
252    
253            @Override
254            public JournalFolder fetchFolder(
255                    long groupId, long parentFolderId, String name) {
256    
257                    return journalFolderPersistence.fetchByG_P_N(
258                            groupId, parentFolderId, name);
259            }
260    
261            @Override
262            public JournalFolder fetchFolder(long groupId, String name) {
263                    return journalFolderPersistence.fetchByG_N(groupId, name);
264            }
265    
266            @Override
267            public List<JournalFolder> getCompanyFolders(
268                    long companyId, int start, int end) {
269    
270                    return journalFolderPersistence.findByCompanyId(companyId, start, end);
271            }
272    
273            @Override
274            public int getCompanyFoldersCount(long companyId) {
275                    return journalFolderPersistence.countByCompanyId(companyId);
276            }
277    
278            @Override
279            public JournalFolder getFolder(long folderId) throws PortalException {
280                    return journalFolderPersistence.findByPrimaryKey(folderId);
281            }
282    
283            @Override
284            public List<JournalFolder> getFolders(long groupId) {
285                    return journalFolderPersistence.findByGroupId(groupId);
286            }
287    
288            @Override
289            public List<JournalFolder> getFolders(long groupId, long parentFolderId) {
290                    return getFolders(
291                            groupId, parentFolderId, WorkflowConstants.STATUS_APPROVED);
292            }
293    
294            @Override
295            public List<JournalFolder> getFolders(
296                    long groupId, long parentFolderId, int status) {
297    
298                    return journalFolderPersistence.findByG_P_S(
299                            groupId, parentFolderId, status);
300            }
301    
302            @Override
303            public List<JournalFolder> getFolders(
304                    long groupId, long parentFolderId, int start, int end) {
305    
306                    return getFolders(
307                            groupId, parentFolderId, WorkflowConstants.STATUS_APPROVED, start,
308                            end);
309            }
310    
311            @Override
312            public List<JournalFolder> getFolders(
313                    long groupId, long parentFolderId, int status, int start, int end) {
314    
315                    return journalFolderPersistence.findByG_P_S(
316                            groupId, parentFolderId, status, start, end);
317            }
318    
319            @Override
320            public List<Object> getFoldersAndArticles(long groupId, long folderId) {
321                    QueryDefinition<?> queryDefinition = new QueryDefinition<Object>(
322                            WorkflowConstants.STATUS_ANY);
323    
324                    return journalFolderFinder.findF_A_ByG_F(
325                            groupId, folderId, queryDefinition);
326            }
327    
328            @Override
329            public List<Object> getFoldersAndArticles(
330                    long groupId, long folderId, int status) {
331    
332                    QueryDefinition<?> queryDefinition = new QueryDefinition<Object>(
333                            status);
334    
335                    return journalFolderFinder.findF_A_ByG_F(
336                            groupId, folderId, queryDefinition);
337            }
338    
339            @Override
340            public List<Object> getFoldersAndArticles(
341                    long groupId, long folderId, int start, int end,
342                    OrderByComparator<?> obc) {
343    
344                    QueryDefinition<?> queryDefinition = new QueryDefinition<Object>(
345                            WorkflowConstants.STATUS_ANY, start, end,
346                            (OrderByComparator<Object>)obc);
347    
348                    return journalFolderFinder.findF_A_ByG_F(
349                            groupId, folderId, queryDefinition);
350            }
351    
352            @Override
353            public int getFoldersAndArticlesCount(
354                    long groupId, List<Long> folderIds, int status) {
355    
356                    QueryDefinition<JournalArticle> queryDefinition =
357                            new QueryDefinition<JournalArticle>(status);
358    
359                    if (folderIds.size() <= PropsValues.SQL_DATA_MAX_PARAMETERS) {
360                            return journalArticleFinder.countByG_F(
361                                    groupId, folderIds, queryDefinition);
362                    }
363                    else {
364                            int start = 0;
365                            int end = PropsValues.SQL_DATA_MAX_PARAMETERS;
366    
367                            int articlesCount = journalArticleFinder.countByG_F(
368                                    groupId, folderIds.subList(start, end), queryDefinition);
369    
370                            folderIds.subList(start, end).clear();
371    
372                            articlesCount += getFoldersAndArticlesCount(
373                                    groupId, folderIds, status);
374    
375                            return articlesCount;
376                    }
377            }
378    
379            @Override
380            public int getFoldersAndArticlesCount(long groupId, long folderId) {
381                    return journalFolderFinder.countF_A_ByG_F(
382                            groupId, folderId,
383                            new QueryDefinition<Object>(WorkflowConstants.STATUS_ANY));
384            }
385    
386            @Override
387            public int getFoldersAndArticlesCount(
388                    long groupId, long folderId, int status) {
389    
390                    return journalFolderFinder.countF_A_ByG_F(
391                            groupId, folderId, new QueryDefinition<Object>(status));
392            }
393    
394            @Override
395            public int getFoldersCount(long groupId, long parentFolderId) {
396                    return getFoldersCount(
397                            groupId, parentFolderId, WorkflowConstants.STATUS_APPROVED);
398            }
399    
400            @Override
401            public int getFoldersCount(long groupId, long parentFolderId, int status) {
402                    return journalFolderPersistence.countByG_P_S(
403                            groupId, parentFolderId, status);
404            }
405    
406            @Override
407            public long getInheritedWorkflowFolderId(long folderId)
408                    throws NoSuchFolderException {
409    
410                    while (folderId != JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
411                            JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
412                                    folderId);
413    
414                            if (folder.getRestrictionType() !=
415                                            JournalFolderConstants.RESTRICTION_TYPE_INHERIT) {
416    
417                                    break;
418                            }
419    
420                            folderId = folder.getParentFolderId();
421                    }
422    
423                    return folderId;
424            }
425    
426            @Override
427            public List<JournalFolder> getNoAssetFolders() {
428                    return journalFolderFinder.findF_ByNoAssets();
429            }
430    
431            @Override
432            public long getOverridedDDMStructuresFolderId(long folderId)
433                    throws NoSuchFolderException {
434    
435                    while (folderId != JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
436                            JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
437                                    folderId);
438    
439                            if (folder.getRestrictionType() ==
440                                            JournalFolderConstants.
441                                                    RESTRICTION_TYPE_DDM_STRUCTURES_AND_WORKFLOW) {
442    
443                                    break;
444                            }
445    
446                            folderId = folder.getParentFolderId();
447                    }
448    
449                    return folderId;
450            }
451    
452            @Override
453            public void getSubfolderIds(
454                    List<Long> folderIds, long groupId, long folderId) {
455    
456                    List<JournalFolder> folders = journalFolderPersistence.findByG_P(
457                            groupId, folderId);
458    
459                    for (JournalFolder folder : folders) {
460                            folderIds.add(folder.getFolderId());
461    
462                            getSubfolderIds(
463                                    folderIds, folder.getGroupId(), folder.getFolderId());
464                    }
465            }
466    
467            @Indexable(type = IndexableType.REINDEX)
468            @Override
469            public JournalFolder moveFolder(
470                            long folderId, long parentFolderId, ServiceContext serviceContext)
471                    throws PortalException {
472    
473                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
474                            folderId);
475    
476                    parentFolderId = getParentFolderId(folder, parentFolderId);
477    
478                    validateFolderDDMStructures(folder.getFolderId(), parentFolderId);
479    
480                    validateFolder(
481                            folder.getFolderId(), folder.getGroupId(), parentFolderId,
482                            folder.getName());
483    
484                    folder.setModifiedDate(serviceContext.getModifiedDate(null));
485                    folder.setParentFolderId(parentFolderId);
486                    folder.setTreePath(folder.buildTreePath());
487                    folder.setExpandoBridgeAttributes(serviceContext);
488    
489                    journalFolderPersistence.update(folder);
490    
491                    rebuildTree(
492                            folder.getCompanyId(), folderId, folder.getTreePath(), true);
493    
494                    return folder;
495            }
496    
497            @Override
498            public JournalFolder moveFolderFromTrash(
499                            long userId, long folderId, long parentFolderId,
500                            ServiceContext serviceContext)
501                    throws PortalException {
502    
503                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
504                            folderId);
505    
506                    if (folder.isInTrashExplicitly()) {
507                            restoreFolderFromTrash(userId, folderId);
508                    }
509                    else {
510    
511                            // Folder
512    
513                            TrashVersion trashVersion = trashVersionLocalService.fetchVersion(
514                                    JournalFolder.class.getName(), folderId);
515    
516                            int status = WorkflowConstants.STATUS_APPROVED;
517    
518                            if (trashVersion != null) {
519                                    status = trashVersion.getStatus();
520                            }
521    
522                            updateStatus(userId, folder, status);
523    
524                            // Trash
525    
526                            if (trashVersion != null) {
527                                    trashVersionLocalService.deleteTrashVersion(trashVersion);
528                            }
529    
530                            // Folders and articles
531    
532                            List<Object> foldersAndArticles =
533                                    journalFolderLocalService.getFoldersAndArticles(
534                                            folder.getGroupId(), folder.getFolderId(),
535                                            WorkflowConstants.STATUS_IN_TRASH);
536    
537                            restoreDependentsFromTrash(foldersAndArticles);
538                    }
539    
540                    return journalFolderLocalService.moveFolder(
541                            folderId, parentFolderId, serviceContext);
542            }
543    
544            @Override
545            public JournalFolder moveFolderToTrash(long userId, long folderId)
546                    throws PortalException {
547    
548                    // Folder
549    
550                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
551                            folderId);
552    
553                    String title = folder.getName();
554    
555                    folder = updateStatus(
556                            userId, folder, WorkflowConstants.STATUS_IN_TRASH);
557    
558                    // Trash
559    
560                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
561    
562                    typeSettingsProperties.put("title", folder.getName());
563    
564                    TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
565                            userId, folder.getGroupId(), JournalFolder.class.getName(),
566                            folder.getFolderId(), folder.getUuid(), null,
567                            WorkflowConstants.STATUS_APPROVED, null, typeSettingsProperties);
568    
569                    folder.setName(TrashUtil.getTrashTitle(trashEntry.getEntryId()));
570    
571                    journalFolderPersistence.update(folder);
572    
573                    // Folders and articles
574    
575                    List<Object> foldersAndArticles =
576                            journalFolderLocalService.getFoldersAndArticles(
577                                    folder.getGroupId(), folder.getFolderId());
578    
579                    moveDependentsToTrash(foldersAndArticles, trashEntry.getEntryId());
580    
581                    // Social
582    
583                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
584    
585                    extraDataJSONObject.put("title", title);
586    
587                    socialActivityLocalService.addActivity(
588                            userId, folder.getGroupId(), JournalFolder.class.getName(),
589                            folder.getFolderId(), SocialActivityConstants.TYPE_MOVE_TO_TRASH,
590                            extraDataJSONObject.toString(), 0);
591    
592                    return folder;
593            }
594    
595            @Override
596            public void rebuildTree(long companyId) throws PortalException {
597                    rebuildTree(
598                            companyId, JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID,
599                            StringPool.SLASH, false);
600            }
601    
602            @Override
603            public void rebuildTree(
604                            long companyId, long parentFolderId, String parentTreePath,
605                            final boolean reindex)
606                    throws PortalException {
607    
608                    TreePathUtil.rebuildTree(
609                            companyId, parentFolderId, parentTreePath,
610                            new TreeModelTasksAdapter<JournalFolder>() {
611    
612                                    @Override
613                                    public List<JournalFolder> findTreeModels(
614                                            long previousId, long companyId, long parentPrimaryKey,
615                                            int size) {
616    
617                                            return journalFolderPersistence.findByF_C_P_NotS(
618                                                    previousId, companyId, parentPrimaryKey,
619                                                    WorkflowConstants.STATUS_IN_TRASH, QueryUtil.ALL_POS,
620                                                    size, new FolderIdComparator(true));
621                                    }
622    
623                                    @Override
624                                    public void rebuildDependentModelsTreePaths(
625                                                    long parentPrimaryKey, String treePath)
626                                            throws PortalException {
627    
628                                            journalArticleLocalService.setTreePaths(
629                                                    parentPrimaryKey, treePath, false);
630                                    }
631    
632                                    @Override
633                                    public void reindexTreeModels(List<TreeModel> treeModels)
634                                            throws PortalException {
635    
636                                            if (!reindex) {
637                                                    return;
638                                            }
639    
640                                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
641                                                    JournalFolder.class);
642    
643                                            for (TreeModel treeModel : treeModels) {
644                                                    indexer.reindex(treeModel);
645                                            }
646                                    }
647    
648                            }
649                    );
650            }
651    
652            @Override
653            public void restoreFolderFromTrash(long userId, long folderId)
654                    throws PortalException {
655    
656                    // Folder
657    
658                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
659                            folderId);
660    
661                    folder.setName(TrashUtil.getOriginalTitle(folder.getName()));
662    
663                    journalFolderPersistence.update(folder);
664    
665                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
666                            JournalFolder.class.getName(), folderId);
667    
668                    updateStatus(userId, folder, trashEntry.getStatus());
669    
670                    // Folders and articles
671    
672                    List<Object> foldersAndArticles =
673                            journalFolderLocalService.getFoldersAndArticles(
674                                    folder.getGroupId(), folder.getFolderId(),
675                                    WorkflowConstants.STATUS_IN_TRASH);
676    
677                    restoreDependentsFromTrash(foldersAndArticles);
678    
679                    // Trash
680    
681                    trashEntryLocalService.deleteEntry(
682                            JournalFolder.class.getName(), folder.getFolderId());
683    
684                    // Social
685    
686                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
687    
688                    extraDataJSONObject.put("title", folder.getName());
689    
690                    socialActivityLocalService.addActivity(
691                            userId, folder.getGroupId(), JournalFolder.class.getName(),
692                            folder.getFolderId(),
693                            SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
694                            extraDataJSONObject.toString(), 0);
695            }
696    
697            @Override
698            public void subscribe(long userId, long groupId, long folderId)
699                    throws PortalException {
700    
701                    if (folderId == JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
702                            folderId = groupId;
703                    }
704    
705                    subscriptionLocalService.addSubscription(
706                            userId, groupId, JournalFolder.class.getName(), folderId);
707            }
708    
709            @Override
710            public void unsubscribe(long userId, long groupId, long folderId)
711                    throws PortalException {
712    
713                    if (folderId == JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
714                            folderId = groupId;
715                    }
716    
717                    subscriptionLocalService.deleteSubscription(
718                            userId, JournalFolder.class.getName(), folderId);
719            }
720    
721            @Override
722            public void updateAsset(
723                            long userId, JournalFolder folder, long[] assetCategoryIds,
724                            String[] assetTagNames, long[] assetLinkEntryIds)
725                    throws PortalException {
726    
727                    AssetEntry assetEntry = assetEntryLocalService.updateEntry(
728                            userId, folder.getGroupId(), folder.getCreateDate(),
729                            folder.getModifiedDate(), JournalFolder.class.getName(),
730                            folder.getFolderId(), folder.getUuid(), 0, assetCategoryIds,
731                            assetTagNames, true, null, null, null, ContentTypes.TEXT_PLAIN,
732                            folder.getName(), folder.getDescription(), null, null, null, 0, 0,
733                            null, false);
734    
735                    assetLinkLocalService.updateLinks(
736                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
737                            AssetLinkConstants.TYPE_RELATED);
738            }
739    
740            @Indexable(type = IndexableType.REINDEX)
741            @Override
742            public JournalFolder updateFolder(
743                            long userId, long folderId, long parentFolderId, String name,
744                            String description, boolean mergeWithParentFolder,
745                            ServiceContext serviceContext)
746                    throws PortalException {
747    
748                    return updateFolder(
749                            userId, folderId, parentFolderId, name, description, new long[0],
750                            JournalFolderConstants.RESTRICTION_TYPE_INHERIT,
751                            mergeWithParentFolder, serviceContext);
752            }
753    
754            @Indexable(type = IndexableType.REINDEX)
755            @Override
756            public JournalFolder updateFolder(
757                            long userId, long folderId, long parentFolderId, String name,
758                            String description, long[] ddmStructureIds, int restrictionType,
759                            boolean mergeWithParentFolder, ServiceContext serviceContext)
760                    throws PortalException {
761    
762                    JournalFolder folder = null;
763    
764                    Set<Long> originalDDMStructureIds = new HashSet<Long>();
765    
766                    if (folderId > JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
767                            originalDDMStructureIds = getDDMStructureIds(
768                                    journalFolderPersistence.getDDMStructures(folderId));
769    
770                            folder = doUpdateFolder(
771                                    userId, folderId, parentFolderId, name, description,
772                                    ddmStructureIds, restrictionType, mergeWithParentFolder,
773                                    serviceContext);
774                    }
775    
776                    List<ObjectValuePair<Long, String>> workflowDefinitionOVPs =
777                            new ArrayList<ObjectValuePair<Long, String>>();
778    
779                    if (restrictionType ==
780                                    JournalFolderConstants.
781                                            RESTRICTION_TYPE_DDM_STRUCTURES_AND_WORKFLOW) {
782    
783                            workflowDefinitionOVPs.add(
784                                    new ObjectValuePair<Long, String>(
785                                            JournalArticleConstants.DDM_STRUCTURE_ID_ALL,
786                                            StringPool.BLANK));
787    
788                            for (long ddmStructureId : ddmStructureIds) {
789                                    String workflowDefinition = ParamUtil.getString(
790                                            serviceContext, "workflowDefinition" + ddmStructureId);
791    
792                                    workflowDefinitionOVPs.add(
793                                            new ObjectValuePair<Long, String>(
794                                                    ddmStructureId, workflowDefinition));
795                            }
796                    }
797                    else if (restrictionType ==
798                                            JournalFolderConstants.RESTRICTION_TYPE_INHERIT) {
799    
800                            if (originalDDMStructureIds.isEmpty()) {
801                                    originalDDMStructureIds.add(
802                                            JournalArticleConstants.DDM_STRUCTURE_ID_ALL);
803                            }
804    
805                            for (long originalDDMStructureId : originalDDMStructureIds) {
806                                    workflowDefinitionOVPs.add(
807                                            new ObjectValuePair<Long, String>(
808                                                    originalDDMStructureId, StringPool.BLANK));
809                            }
810                    }
811                    else if (restrictionType ==
812                                            JournalFolderConstants.RESTRICTION_TYPE_WORKFLOW) {
813    
814                            String workflowDefinition = ParamUtil.getString(
815                                    serviceContext,
816                                    "workflowDefinition" +
817                                            JournalArticleConstants.DDM_STRUCTURE_ID_ALL);
818    
819                            workflowDefinitionOVPs.add(
820                                    new ObjectValuePair<Long, String>(
821                                            JournalArticleConstants.DDM_STRUCTURE_ID_ALL,
822                                            workflowDefinition));
823    
824                            for (long originalDDMStructureId : originalDDMStructureIds) {
825                                    workflowDefinitionOVPs.add(
826                                            new ObjectValuePair<Long, String>(
827                                                    originalDDMStructureId, StringPool.BLANK));
828                            }
829                    }
830    
831                    workflowDefinitionLinkLocalService.updateWorkflowDefinitionLinks(
832                            serviceContext.getUserId(), serviceContext.getCompanyId(),
833                            serviceContext.getScopeGroupId(), JournalFolder.class.getName(),
834                            folderId, workflowDefinitionOVPs);
835    
836                    return folder;
837            }
838    
839            @Override
840            public void updateFolderDDMStructures(
841                    JournalFolder folder, long[] ddmStructureIdsArray) {
842    
843                    Set<Long> ddmStructureIds = SetUtil.fromArray(ddmStructureIdsArray);
844                    Set<Long> originalDDMStructureIds = getDDMStructureIds(
845                            journalFolderPersistence.getDDMStructures(folder.getFolderId()));
846    
847                    if (ddmStructureIds.equals(originalDDMStructureIds)) {
848                            return;
849                    }
850    
851                    for (Long ddmStructureId : ddmStructureIds) {
852                            if (!originalDDMStructureIds.contains(ddmStructureId)) {
853                                    journalFolderPersistence.addDDMStructure(
854                                            folder.getFolderId(), ddmStructureId);
855                            }
856                    }
857    
858                    for (Long originalDDMStructureId : originalDDMStructureIds) {
859                            if (!ddmStructureIds.contains(originalDDMStructureId)) {
860                                    journalFolderPersistence.removeDDMStructure(
861                                            folder.getFolderId(), originalDDMStructureId);
862                            }
863                    }
864            }
865    
866            @Override
867            public JournalFolder updateStatus(
868                            long userId, JournalFolder folder, int status)
869                    throws PortalException {
870    
871                    // Folder
872    
873                    User user = userPersistence.findByPrimaryKey(userId);
874    
875                    folder.setStatus(status);
876                    folder.setStatusByUserId(userId);
877                    folder.setStatusByUserName(user.getFullName());
878                    folder.setStatusDate(new Date());
879    
880                    journalFolderPersistence.update(folder);
881    
882                    // Asset
883    
884                    if (status == WorkflowConstants.STATUS_APPROVED) {
885                            assetEntryLocalService.updateVisible(
886                                    JournalFolder.class.getName(), folder.getFolderId(), true);
887                    }
888                    else if (status == WorkflowConstants.STATUS_IN_TRASH) {
889                            assetEntryLocalService.updateVisible(
890                                    JournalFolder.class.getName(), folder.getFolderId(), false);
891                    }
892    
893                    // Index
894    
895                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
896                            JournalFolder.class);
897    
898                    indexer.reindex(folder);
899    
900                    return folder;
901            }
902    
903            @Override
904            public void validateFolderDDMStructures(long folderId, long parentFolderId)
905                    throws PortalException {
906    
907                    JournalFolder folder = journalFolderLocalService.fetchFolder(folderId);
908    
909                    int restrictionType =
910                            JournalFolderConstants.RESTRICTION_TYPE_DDM_STRUCTURES_AND_WORKFLOW;
911    
912                    JournalFolder parentFolder = journalFolderLocalService.fetchFolder(
913                            parentFolderId);
914    
915                    if (parentFolder != null) {
916                            restrictionType = parentFolder.getRestrictionType();
917                    }
918    
919                    List<DDMStructure> folderDDMStructures =
920                            ddmStructureLocalService.getJournalFolderStructures(
921                                    PortalUtil.getCurrentAndAncestorSiteGroupIds(
922                                            folder.getGroupId()),
923                                    parentFolderId, restrictionType);
924    
925                    long[] ddmStructureIds = new long[folderDDMStructures.size()];
926    
927                    for (int i = 0; i < folderDDMStructures.size(); i++) {
928                            DDMStructure folderDDMStructure = folderDDMStructures.get(i);
929    
930                            ddmStructureIds[i] = folderDDMStructure.getStructureId();
931                    }
932    
933                    validateArticleDDMStructures(folderId, ddmStructureIds);
934            }
935    
936            protected void deleteWorkflowDefinitionLink(JournalFolder folder) {
937                    List<Long> ddmStructureIds = new ArrayList<Long>();
938    
939                    for (DDMStructure ddmStructure :
940                                    ddmStructureLocalService.getJournalFolderDDMStructures(
941                                            folder.getFolderId())) {
942    
943                            ddmStructureIds.add(ddmStructure.getStructureId());
944                    }
945    
946                    if (ddmStructureIds.isEmpty()) {
947                            ddmStructureIds.add(JournalArticleConstants.DDM_STRUCTURE_ID_ALL);
948                    }
949    
950                    for (long ddmStructureId : ddmStructureIds) {
951                            WorkflowDefinitionLink workflowDefinitionLink =
952                                    workflowDefinitionLinkLocalService.fetchWorkflowDefinitionLink(
953                                            folder.getCompanyId(), folder.getGroupId(),
954                                            JournalFolder.class.getName(), folder.getFolderId(),
955                                            ddmStructureId);
956    
957                            if (workflowDefinitionLink == null) {
958                                    continue;
959                            }
960    
961                            workflowDefinitionLinkLocalService.deleteWorkflowDefinitionLink(
962                                    workflowDefinitionLink);
963                    }
964            }
965    
966            protected JournalFolder doUpdateFolder(
967                            long userId, long folderId, long parentFolderId, String name,
968                            String description, long[] ddmStructureIds, int restrictionType,
969                            boolean mergeWithParentFolder, ServiceContext serviceContext)
970                    throws PortalException {
971    
972                    // Merge folders
973    
974                    if (restrictionType !=
975                                    JournalFolderConstants.
976                                            RESTRICTION_TYPE_DDM_STRUCTURES_AND_WORKFLOW) {
977    
978                            ddmStructureIds = new long[0];
979                    }
980    
981                    validateArticleDDMStructures(folderId, ddmStructureIds);
982    
983                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
984                            folderId);
985    
986                    parentFolderId = getParentFolderId(folder, parentFolderId);
987    
988                    if (mergeWithParentFolder && (folderId != parentFolderId)) {
989                            mergeFolders(folder, parentFolderId);
990    
991                            return folder;
992                    }
993    
994                    // Folder
995    
996                    validateFolder(folderId, folder.getGroupId(), parentFolderId, name);
997    
998                    folder.setModifiedDate(serviceContext.getModifiedDate(null));
999                    folder.setParentFolderId(parentFolderId);
1000                    folder.setTreePath(folder.buildTreePath());
1001                    folder.setName(name);
1002                    folder.setDescription(description);
1003                    folder.setRestrictionType(restrictionType);
1004                    folder.setExpandoBridgeAttributes(serviceContext);
1005    
1006                    journalFolderPersistence.update(folder);
1007    
1008                    // Asset
1009    
1010                    updateAsset(
1011                            userId, folder, serviceContext.getAssetCategoryIds(),
1012                            serviceContext.getAssetTagNames(),
1013                            serviceContext.getAssetLinkEntryIds());
1014    
1015                    // Dynamic data mapping
1016    
1017                    if (ddmStructureIds != null) {
1018                            updateFolderDDMStructures(folder, ddmStructureIds);
1019                    }
1020    
1021                    return folder;
1022            }
1023    
1024            protected Set<Long> getDDMStructureIds(List<DDMStructure> ddmStructures) {
1025                    Set<Long> ddmStructureIds = new HashSet<Long>();
1026    
1027                    for (DDMStructure ddmStructure : ddmStructures) {
1028                            ddmStructureIds.add(ddmStructure.getStructureId());
1029                    }
1030    
1031                    return ddmStructureIds;
1032            }
1033    
1034            protected long getParentFolderId(
1035                    JournalFolder folder, long parentFolderId) {
1036    
1037                    if (parentFolderId == JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1038                            return parentFolderId;
1039                    }
1040    
1041                    if (folder.getFolderId() == parentFolderId) {
1042                            return folder.getParentFolderId();
1043                    }
1044    
1045                    JournalFolder parentFolder = journalFolderPersistence.fetchByPrimaryKey(
1046                            parentFolderId);
1047    
1048                    if ((parentFolder == null) ||
1049                            (folder.getGroupId() != parentFolder.getGroupId())) {
1050    
1051                            return folder.getParentFolderId();
1052                    }
1053    
1054                    List<Long> subfolderIds = new ArrayList<Long>();
1055    
1056                    getSubfolderIds(
1057                            subfolderIds, folder.getGroupId(), folder.getFolderId());
1058    
1059                    if (subfolderIds.contains(parentFolderId)) {
1060                            return folder.getParentFolderId();
1061                    }
1062    
1063                    return parentFolderId;
1064            }
1065    
1066            protected long getParentFolderId(long groupId, long parentFolderId) {
1067                    if (parentFolderId != JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1068                            JournalFolder parentFolder =
1069                                    journalFolderPersistence.fetchByPrimaryKey(parentFolderId);
1070    
1071                            if ((parentFolder == null) ||
1072                                    (groupId != parentFolder.getGroupId())) {
1073    
1074                                    parentFolderId =
1075                                            JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID;
1076                            }
1077                    }
1078    
1079                    return parentFolderId;
1080            }
1081    
1082            protected void mergeFolders(JournalFolder fromFolder, long toFolderId)
1083                    throws PortalException {
1084    
1085                    List<JournalFolder> folders = journalFolderPersistence.findByG_P(
1086                            fromFolder.getGroupId(), fromFolder.getFolderId());
1087    
1088                    for (JournalFolder folder : folders) {
1089                            mergeFolders(folder, toFolderId);
1090                    }
1091    
1092                    List<JournalArticle> articles = journalArticlePersistence.findByG_F(
1093                            fromFolder.getGroupId(), fromFolder.getFolderId());
1094    
1095                    for (JournalArticle article : articles) {
1096                            article.setFolderId(toFolderId);
1097    
1098                            journalArticlePersistence.update(article);
1099    
1100                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1101                                    JournalArticle.class);
1102    
1103                            indexer.reindex(article);
1104                    }
1105    
1106                    journalFolderLocalService.deleteFolder(fromFolder);
1107            }
1108    
1109            protected void moveDependentsToTrash(
1110                            List<Object> foldersAndArticles, long trashEntryId)
1111                    throws PortalException {
1112    
1113                    for (Object object : foldersAndArticles) {
1114                            if (object instanceof JournalArticle) {
1115    
1116                                    // Article
1117    
1118                                    JournalArticle article = (JournalArticle)object;
1119    
1120                                    if (article.getStatus() == WorkflowConstants.STATUS_IN_TRASH) {
1121                                            continue;
1122                                    }
1123    
1124                                    // Articles
1125    
1126                                    List<JournalArticle> articles =
1127                                            journalArticlePersistence.findByG_A(
1128                                                    article.getGroupId(), article.getArticleId());
1129    
1130                                    for (JournalArticle curArticle : articles) {
1131    
1132                                            // Article
1133    
1134                                            int curArticleOldStatus = curArticle.getStatus();
1135    
1136                                            curArticle.setStatus(WorkflowConstants.STATUS_IN_TRASH);
1137    
1138                                            journalArticlePersistence.update(curArticle);
1139    
1140                                            // Trash
1141    
1142                                            int status = curArticleOldStatus;
1143    
1144                                            if (curArticleOldStatus ==
1145                                                            WorkflowConstants.STATUS_PENDING) {
1146    
1147                                                    status = WorkflowConstants.STATUS_DRAFT;
1148                                            }
1149    
1150                                            if (curArticleOldStatus !=
1151                                                            WorkflowConstants.STATUS_APPROVED) {
1152    
1153                                                    trashVersionLocalService.addTrashVersion(
1154                                                            trashEntryId, JournalArticle.class.getName(),
1155                                                            curArticle.getId(), status, null);
1156                                            }
1157    
1158                                            // Workflow
1159    
1160                                            if (curArticleOldStatus ==
1161                                                            WorkflowConstants.STATUS_PENDING) {
1162    
1163                                                    workflowInstanceLinkLocalService.
1164                                                            deleteWorkflowInstanceLink(
1165                                                                    curArticle.getCompanyId(),
1166                                                                    curArticle.getGroupId(),
1167                                                                    JournalArticle.class.getName(),
1168                                                                    curArticle.getId());
1169                                            }
1170                                    }
1171    
1172                                    // Asset
1173    
1174                                    assetEntryLocalService.updateVisible(
1175                                            JournalArticle.class.getName(),
1176                                            article.getResourcePrimKey(), false);
1177    
1178                                    // Indexer
1179    
1180                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1181                                            JournalArticle.class);
1182    
1183                                    indexer.reindex(article);
1184                            }
1185                            else if (object instanceof JournalFolder) {
1186    
1187                                    // Folder
1188    
1189                                    JournalFolder folder = (JournalFolder)object;
1190    
1191                                    if (folder.isInTrashExplicitly()) {
1192                                            continue;
1193                                    }
1194    
1195                                    int oldStatus = folder.getStatus();
1196    
1197                                    folder.setStatus(WorkflowConstants.STATUS_IN_TRASH);
1198    
1199                                    journalFolderPersistence.update(folder);
1200    
1201                                    // Trash
1202    
1203                                    if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
1204                                            trashVersionLocalService.addTrashVersion(
1205                                                    trashEntryId, JournalFolder.class.getName(),
1206                                                    folder.getFolderId(), oldStatus, null);
1207                                    }
1208    
1209                                    // Folders and articles
1210    
1211                                    List<Object> curFoldersAndArticles = getFoldersAndArticles(
1212                                            folder.getGroupId(), folder.getFolderId());
1213    
1214                                    moveDependentsToTrash(curFoldersAndArticles, trashEntryId);
1215    
1216                                    // Asset
1217    
1218                                    assetEntryLocalService.updateVisible(
1219                                            JournalFolder.class.getName(), folder.getFolderId(), false);
1220    
1221                                    // Index
1222    
1223                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1224                                            JournalFolder.class);
1225    
1226                                    indexer.reindex(folder);
1227                            }
1228                    }
1229            }
1230    
1231            protected void restoreDependentsFromTrash(List<Object> foldersAndArticles)
1232                    throws PortalException {
1233    
1234                    for (Object object : foldersAndArticles) {
1235                            if (object instanceof JournalArticle) {
1236    
1237                                    // Article
1238    
1239                                    JournalArticle article = (JournalArticle)object;
1240    
1241                                    if (!article.isInTrashImplicitly()) {
1242                                            continue;
1243                                    }
1244    
1245                                    TrashVersion trashVersion =
1246                                            trashVersionLocalService.fetchVersion(
1247                                                    JournalArticle.class.getName(), article.getId());
1248    
1249                                    int oldStatus = WorkflowConstants.STATUS_APPROVED;
1250    
1251                                    if (trashVersion != null) {
1252                                            oldStatus = trashVersion.getStatus();
1253                                    }
1254    
1255                                    // Articles
1256    
1257                                    List<JournalArticle> articles =
1258                                            journalArticlePersistence.findByG_A(
1259                                                    article.getGroupId(), article.getArticleId());
1260    
1261                                    for (JournalArticle curArticle : articles) {
1262    
1263                                            // Article
1264    
1265                                            trashVersion = trashVersionLocalService.fetchVersion(
1266                                                    JournalArticle.class.getName(), curArticle.getId());
1267    
1268                                            int curArticleOldStatus = WorkflowConstants.STATUS_APPROVED;
1269    
1270                                            if (trashVersion != null) {
1271                                                    curArticleOldStatus = trashVersion.getStatus();
1272                                            }
1273    
1274                                            curArticle.setStatus(curArticleOldStatus);
1275    
1276                                            journalArticlePersistence.update(curArticle);
1277    
1278                                            // Trash
1279    
1280                                            if (trashVersion != null) {
1281                                                    trashVersionLocalService.deleteTrashVersion(
1282                                                            trashVersion);
1283                                            }
1284                                    }
1285    
1286                                    // Asset
1287    
1288                                    if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
1289                                            assetEntryLocalService.updateVisible(
1290                                                    JournalArticle.class.getName(),
1291                                                    article.getResourcePrimKey(), true);
1292                                    }
1293    
1294                                    // Indexer
1295    
1296                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1297                                            JournalArticle.class);
1298    
1299                                    indexer.reindex(article);
1300                            }
1301                            else if (object instanceof JournalFolder) {
1302    
1303                                    // Folder
1304    
1305                                    JournalFolder folder = (JournalFolder)object;
1306    
1307                                    if (!folder.isInTrashImplicitly()) {
1308                                            continue;
1309                                    }
1310    
1311                                    TrashVersion trashVersion =
1312                                            trashVersionLocalService.fetchVersion(
1313                                                    JournalFolder.class.getName(), folder.getFolderId());
1314    
1315                                    int oldStatus = WorkflowConstants.STATUS_APPROVED;
1316    
1317                                    if (trashVersion != null) {
1318                                            oldStatus = trashVersion.getStatus();
1319                                    }
1320    
1321                                    folder.setStatus(oldStatus);
1322    
1323                                    journalFolderPersistence.update(folder);
1324    
1325                                    // Folders and articles
1326    
1327                                    List<Object> curFoldersAndArticles = getFoldersAndArticles(
1328                                            folder.getGroupId(), folder.getFolderId(),
1329                                            WorkflowConstants.STATUS_IN_TRASH);
1330    
1331                                    restoreDependentsFromTrash(curFoldersAndArticles);
1332    
1333                                    // Trash
1334    
1335                                    if (trashVersion != null) {
1336                                            trashVersionLocalService.deleteTrashVersion(trashVersion);
1337                                    }
1338    
1339                                    // Asset
1340    
1341                                    assetEntryLocalService.updateVisible(
1342                                            JournalFolder.class.getName(), folder.getFolderId(), true);
1343    
1344                                    // Index
1345    
1346                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1347                                            JournalFolder.class);
1348    
1349                                    indexer.reindex(folder);
1350                            }
1351                    }
1352            }
1353    
1354            protected void validateArticleDDMStructures(
1355                            long folderId, long[] ddmStructureIds)
1356                    throws PortalException {
1357    
1358                    if (ArrayUtil.isEmpty(ddmStructureIds)) {
1359                            return;
1360                    }
1361    
1362                    JournalFolder folder = journalFolderPersistence.findByPrimaryKey(
1363                            folderId);
1364    
1365                    List<JournalArticle> articles = journalArticleLocalService.getArticles(
1366                            folder.getGroupId(), folderId);
1367    
1368                    if (!articles.isEmpty()) {
1369                            long classNameId = classNameLocalService.getClassNameId(
1370                                    JournalArticle.class);
1371    
1372                            for (JournalArticle article : articles) {
1373                                    DDMStructure ddmStructure =
1374                                            ddmStructureLocalService.fetchStructure(
1375                                                    article.getGroupId(), classNameId,
1376                                                    article.getDDMStructureKey(), true);
1377    
1378                                    if (ddmStructure == null) {
1379                                            throw new InvalidDDMStructureException();
1380                                    }
1381    
1382                                    if (!ArrayUtil.contains(
1383                                                    ddmStructureIds, ddmStructure.getStructureId())) {
1384    
1385                                            throw new InvalidDDMStructureException();
1386                                    }
1387                            }
1388                    }
1389    
1390                    List<JournalFolder> folders = journalFolderPersistence.findByG_P(
1391                            folder.getGroupId(), folder.getFolderId());
1392    
1393                    if (folders.isEmpty()) {
1394                            return;
1395                    }
1396    
1397                    for (JournalFolder curFolder : folders) {
1398                            validateArticleDDMStructures(
1399                                    curFolder.getFolderId(), ddmStructureIds);
1400                    }
1401            }
1402    
1403            protected void validateFolder(
1404                            long folderId, long groupId, long parentFolderId, String name)
1405                    throws PortalException {
1406    
1407                    validateFolderName(name);
1408    
1409                    JournalFolder folder = journalFolderPersistence.fetchByG_P_N(
1410                            groupId, parentFolderId, name);
1411    
1412                    if ((folder != null) && (folder.getFolderId() != folderId)) {
1413                            throw new DuplicateFolderNameException(name);
1414                    }
1415            }
1416    
1417            protected void validateFolderName(String name) throws PortalException {
1418                    if (!AssetUtil.isValidWord(name)) {
1419                            throw new FolderNameException();
1420                    }
1421    
1422                    if (name.contains("\\\\") || name.contains("//")) {
1423                            throw new FolderNameException();
1424                    }
1425            }
1426    
1427    }