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.messageboards.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.search.Indexer;
022    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
023    import com.liferay.portal.kernel.systemevent.SystemEvent;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.kernel.workflow.WorkflowConstants;
026    import com.liferay.portal.model.ResourceConstants;
027    import com.liferay.portal.model.SystemEventConstants;
028    import com.liferay.portal.model.User;
029    import com.liferay.portal.service.ServiceContext;
030    import com.liferay.portlet.messageboards.CategoryNameException;
031    import com.liferay.portlet.messageboards.NoSuchMailingListException;
032    import com.liferay.portlet.messageboards.model.MBCategory;
033    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
034    import com.liferay.portlet.messageboards.model.MBMailingList;
035    import com.liferay.portlet.messageboards.model.MBMessage;
036    import com.liferay.portlet.messageboards.model.MBThread;
037    import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
038    import com.liferay.portlet.messageboards.service.base.MBCategoryLocalServiceBaseImpl;
039    import com.liferay.portlet.trash.NoSuchEntryException;
040    import com.liferay.portlet.trash.model.TrashEntry;
041    import com.liferay.portlet.trash.model.TrashVersion;
042    
043    import java.util.ArrayList;
044    import java.util.Date;
045    import java.util.List;
046    
047    /**
048     * @author Brian Wing Shun Chan
049     * @author Wesley Gong
050     */
051    public class MBCategoryLocalServiceImpl extends MBCategoryLocalServiceBaseImpl {
052    
053            @Override
054            public MBCategory addCategory(
055                            long userId, long parentCategoryId, String name, String description,
056                            ServiceContext serviceContext)
057                    throws PortalException, SystemException {
058    
059                    return addCategory(
060                            userId, parentCategoryId, name, description,
061                            MBCategoryConstants.DEFAULT_DISPLAY_STYLE, null, null, null, 0,
062                            false, null, null, 0, null, false, null, 0, false, null, null,
063                            false, false, serviceContext);
064            }
065    
066            @Override
067            public MBCategory addCategory(
068                            long userId, long parentCategoryId, String name, String description,
069                            String displayStyle, String emailAddress, String inProtocol,
070                            String inServerName, int inServerPort, boolean inUseSSL,
071                            String inUserName, String inPassword, int inReadInterval,
072                            String outEmailAddress, boolean outCustom, String outServerName,
073                            int outServerPort, boolean outUseSSL, String outUserName,
074                            String outPassword, boolean allowAnonymous,
075                            boolean mailingListActive, ServiceContext serviceContext)
076                    throws PortalException, SystemException {
077    
078                    // Category
079    
080                    User user = userPersistence.findByPrimaryKey(userId);
081                    long groupId = serviceContext.getScopeGroupId();
082                    parentCategoryId = getParentCategoryId(groupId, parentCategoryId);
083                    Date now = new Date();
084    
085                    validate(name);
086    
087                    long categoryId = counterLocalService.increment();
088    
089                    MBCategory category = mbCategoryPersistence.create(categoryId);
090    
091                    category.setUuid(serviceContext.getUuid());
092                    category.setGroupId(groupId);
093                    category.setCompanyId(user.getCompanyId());
094                    category.setUserId(user.getUserId());
095                    category.setUserName(user.getFullName());
096                    category.setCreateDate(serviceContext.getCreateDate(now));
097                    category.setModifiedDate(serviceContext.getModifiedDate(now));
098                    category.setParentCategoryId(parentCategoryId);
099                    category.setName(name);
100                    category.setDescription(description);
101                    category.setDisplayStyle(displayStyle);
102                    category.setExpandoBridgeAttributes(serviceContext);
103    
104                    mbCategoryPersistence.update(category);
105    
106                    // Resources
107    
108                    if (serviceContext.isAddGroupPermissions() ||
109                            serviceContext.isAddGuestPermissions()) {
110    
111                            addCategoryResources(
112                                    category, serviceContext.isAddGroupPermissions(),
113                                    serviceContext.isAddGuestPermissions());
114                    }
115                    else {
116                            addCategoryResources(
117                                    category, serviceContext.getGroupPermissions(),
118                                    serviceContext.getGuestPermissions());
119                    }
120    
121                    // Mailing list
122    
123                    mbMailingListLocalService.addMailingList(
124                            userId, groupId, category.getCategoryId(), emailAddress, inProtocol,
125                            inServerName, inServerPort, inUseSSL, inUserName, inPassword,
126                            inReadInterval, outEmailAddress, outCustom, outServerName,
127                            outServerPort, outUseSSL, outUserName, outPassword, allowAnonymous,
128                            mailingListActive, serviceContext);
129    
130                    return category;
131            }
132    
133            @Override
134            public void addCategoryResources(
135                            long categoryId, boolean addGroupPermissions,
136                            boolean addGuestPermissions)
137                    throws PortalException, SystemException {
138    
139                    if ((categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) ||
140                            (categoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
141    
142                            return;
143                    }
144    
145                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
146                            categoryId);
147    
148                    addCategoryResources(
149                            category, addGroupPermissions, addGuestPermissions);
150            }
151    
152            @Override
153            public void addCategoryResources(
154                            long categoryId, String[] groupPermissions,
155                            String[] guestPermissions)
156                    throws PortalException, SystemException {
157    
158                    if ((categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) ||
159                            (categoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
160    
161                            return;
162                    }
163    
164                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
165                            categoryId);
166    
167                    addCategoryResources(category, groupPermissions, guestPermissions);
168            }
169    
170            @Override
171            public void addCategoryResources(
172                            MBCategory category, boolean addGroupPermissions,
173                            boolean addGuestPermissions)
174                    throws PortalException, SystemException {
175    
176                    resourceLocalService.addResources(
177                            category.getCompanyId(), category.getGroupId(),
178                            category.getUserId(), MBCategory.class.getName(),
179                            category.getCategoryId(), false, addGroupPermissions,
180                            addGuestPermissions);
181            }
182    
183            @Override
184            public void addCategoryResources(
185                            MBCategory category, String[] groupPermissions,
186                            String[] guestPermissions)
187                    throws PortalException, SystemException {
188    
189                    resourceLocalService.addModelResources(
190                            category.getCompanyId(), category.getGroupId(),
191                            category.getUserId(), MBCategory.class.getName(),
192                            category.getCategoryId(), groupPermissions, guestPermissions);
193            }
194    
195            @Override
196            public void deleteCategories(long groupId)
197                    throws PortalException, SystemException {
198    
199                    List<MBCategory> categories = mbCategoryPersistence.findByGroupId(
200                            groupId);
201    
202                    for (MBCategory category : categories) {
203                            mbCategoryLocalService.deleteCategory(category);
204                    }
205            }
206    
207            @Override
208            public void deleteCategory(long categoryId)
209                    throws PortalException, SystemException {
210    
211                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
212                            categoryId);
213    
214                    mbCategoryLocalService.deleteCategory(category);
215            }
216    
217            @Override
218            @SystemEvent(
219                    action = SystemEventConstants.ACTION_SKIP,
220                    type = SystemEventConstants.TYPE_DELETE)
221            public void deleteCategory(MBCategory category)
222                    throws PortalException, SystemException {
223    
224                    deleteCategory(category, true);
225            }
226    
227            @Override
228            @SystemEvent(
229                    action = SystemEventConstants.ACTION_SKIP,
230                    type = SystemEventConstants.TYPE_DELETE)
231            public void deleteCategory(
232                            MBCategory category, boolean includeTrashedEntries)
233                    throws PortalException, SystemException {
234    
235                    // Categories
236    
237                    List<MBCategory> categories = mbCategoryPersistence.findByG_P(
238                            category.getGroupId(), category.getCategoryId());
239    
240                    for (MBCategory curCategory : categories) {
241                            if (includeTrashedEntries || !curCategory.isInTrash()) {
242                                    deleteCategory(curCategory, includeTrashedEntries);
243                            }
244                    }
245    
246                    // Indexer
247    
248                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
249                            MBMessage.class);
250    
251                    indexer.delete(category);
252    
253                    // Threads
254    
255                    mbThreadLocalService.deleteThreads(
256                            category.getGroupId(), category.getCategoryId(),
257                            includeTrashedEntries);
258    
259                    // Mailing list
260    
261                    try {
262                            mbMailingListLocalService.deleteCategoryMailingList(
263                                    category.getGroupId(), category.getCategoryId());
264                    }
265                    catch (NoSuchMailingListException nsmle) {
266                    }
267    
268                    // Subscriptions
269    
270                    subscriptionLocalService.deleteSubscriptions(
271                            category.getCompanyId(), MBCategory.class.getName(),
272                            category.getCategoryId());
273    
274                    // Expando
275    
276                    expandoRowLocalService.deleteRows(category.getCategoryId());
277    
278                    // Resources
279    
280                    resourceLocalService.deleteResource(
281                            category.getCompanyId(), MBCategory.class.getName(),
282                            ResourceConstants.SCOPE_INDIVIDUAL, category.getCategoryId());
283    
284                    // Trash
285    
286                    trashEntryLocalService.deleteEntry(
287                            MBCategory.class.getName(), category.getCategoryId());
288    
289                    // Category
290    
291                    mbCategoryPersistence.remove(category);
292            }
293    
294            @Override
295            public List<MBCategory> getCategories(long groupId) throws SystemException {
296                    return mbCategoryPersistence.findByGroupId(groupId);
297            }
298    
299            @Override
300            public List<MBCategory> getCategories(long groupId, int status)
301                    throws SystemException {
302    
303                    return mbCategoryPersistence.findByG_S(groupId, status);
304            }
305    
306            @Override
307            public List<MBCategory> getCategories(
308                            long groupId, long parentCategoryId, int start, int end)
309                    throws SystemException {
310    
311                    return mbCategoryPersistence.findByG_P(
312                            groupId, parentCategoryId, start, end);
313            }
314    
315            @Override
316            public List<MBCategory> getCategories(
317                            long groupId, long parentCategoryId, int status, int start, int end)
318                    throws SystemException {
319    
320                    if (status == WorkflowConstants.STATUS_ANY) {
321                            return mbCategoryPersistence.findByG_P(
322                                    groupId, parentCategoryId, start, end);
323                    }
324    
325                    return mbCategoryPersistence.findByG_P_S(
326                            groupId, parentCategoryId, status, start, end);
327            }
328    
329            @Override
330            public List<MBCategory> getCategories(
331                            long groupId, long[] parentCategoryIds, int start, int end)
332                    throws SystemException {
333    
334                    return mbCategoryPersistence.findByG_P(
335                            groupId, parentCategoryIds, start, end);
336            }
337    
338            @Override
339            public List<MBCategory> getCategories(
340                            long groupId, long[] parentCategoryIds, int status, int start,
341                            int end)
342                    throws SystemException {
343    
344                    if (status == WorkflowConstants.STATUS_ANY) {
345                            return mbCategoryPersistence.findByG_P(
346                                    groupId, parentCategoryIds, start, end);
347                    }
348    
349                    return mbCategoryPersistence.findByG_P_S(
350                            groupId, parentCategoryIds, status, start, end);
351            }
352    
353            @Override
354            public List<Object> getCategoriesAndThreads(long groupId, long categoryId)
355                    throws SystemException {
356    
357                    List<Object> categoriesAndThreads = new ArrayList<Object>();
358    
359                    List<MBCategory> categories = getCategories(
360                            groupId, categoryId, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
361    
362                    categoriesAndThreads.addAll(categories);
363    
364                    List<MBThread> threads = mbThreadLocalService.getThreads(
365                            groupId, categoryId, WorkflowConstants.STATUS_ANY,
366                            QueryUtil.ALL_POS, QueryUtil.ALL_POS);
367    
368                    categoriesAndThreads.addAll(threads);
369    
370                    return categoriesAndThreads;
371            }
372    
373            @Override
374            public int getCategoriesCount(long groupId) throws SystemException {
375                    return mbCategoryPersistence.countByGroupId(groupId);
376            }
377    
378            @Override
379            public int getCategoriesCount(long groupId, int status)
380                    throws SystemException {
381    
382                    return mbCategoryPersistence.countByG_S(groupId, status);
383            }
384    
385            @Override
386            public int getCategoriesCount(long groupId, long parentCategoryId)
387                    throws SystemException {
388    
389                    return mbCategoryPersistence.countByG_P(groupId, parentCategoryId);
390            }
391    
392            @Override
393            public int getCategoriesCount(
394                            long groupId, long parentCategoryId, int status)
395                    throws SystemException {
396    
397                    if (status == WorkflowConstants.STATUS_ANY) {
398                            return mbCategoryPersistence.countByG_P(groupId, parentCategoryId);
399                    }
400    
401                    return mbCategoryPersistence.countByG_P_S(
402                            groupId, parentCategoryId, status);
403            }
404    
405            @Override
406            public int getCategoriesCount(long groupId, long[] parentCategoryIds)
407                    throws SystemException {
408    
409                    return mbCategoryPersistence.countByG_P(groupId, parentCategoryIds);
410            }
411    
412            @Override
413            public int getCategoriesCount(
414                            long groupId, long[] parentCategoryIds, int status)
415                    throws SystemException {
416    
417                    if (status == WorkflowConstants.STATUS_ANY) {
418                            return mbCategoryPersistence.countByG_P(groupId, parentCategoryIds);
419                    }
420    
421                    return mbCategoryPersistence.countByG_P_S(
422                            groupId, parentCategoryIds, status);
423            }
424    
425            @Override
426            public MBCategory getCategory(long categoryId)
427                    throws PortalException, SystemException {
428    
429                    MBCategory category = null;
430    
431                    if ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
432                            (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
433    
434                            category = mbCategoryPersistence.findByPrimaryKey(categoryId);
435                    }
436                    else {
437                            category = new MBCategoryImpl();
438    
439                            category.setCategoryId(categoryId);
440                            category.setParentCategoryId(categoryId);
441                    }
442    
443                    return category;
444            }
445    
446            @Override
447            public List<MBCategory> getCompanyCategories(
448                            long companyId, int start, int end)
449                    throws SystemException {
450    
451                    return mbCategoryPersistence.findByCompanyId(companyId, start, end);
452            }
453    
454            @Override
455            public int getCompanyCategoriesCount(long companyId)
456                    throws SystemException {
457    
458                    return mbCategoryPersistence.countByCompanyId(companyId);
459            }
460    
461            @Override
462            public List<Long> getSubcategoryIds(
463                            List<Long> categoryIds, long groupId, long categoryId)
464                    throws SystemException {
465    
466                    List<MBCategory> categories = mbCategoryPersistence.findByG_P(
467                            groupId, categoryId);
468    
469                    for (MBCategory category : categories) {
470                            categoryIds.add(category.getCategoryId());
471    
472                            getSubcategoryIds(
473                                    categoryIds, category.getGroupId(), category.getCategoryId());
474                    }
475    
476                    return categoryIds;
477            }
478    
479            @Override
480            public List<MBCategory> getSubscribedCategories(
481                            long groupId, long userId, int start, int end)
482                    throws SystemException {
483    
484                    QueryDefinition queryDefinition = new QueryDefinition(
485                            WorkflowConstants.STATUS_ANY, start, end, null);
486    
487                    return mbCategoryFinder.findByS_G_U_P(
488                            groupId, userId, null, queryDefinition);
489            }
490    
491            @Override
492            public int getSubscribedCategoriesCount(long groupId, long userId)
493                    throws SystemException {
494    
495                    QueryDefinition queryDefinition = new QueryDefinition(
496                            WorkflowConstants.STATUS_ANY);
497    
498                    return mbCategoryFinder.countByS_G_U_P(
499                            groupId, userId, null, queryDefinition);
500            }
501    
502            @Override
503            public void moveCategoriesToTrash(long groupId, long userId)
504                    throws PortalException, SystemException {
505    
506                    List<MBCategory> categories = mbCategoryPersistence.findByGroupId(
507                            groupId);
508    
509                    for (MBCategory category : categories) {
510                            moveCategoryToTrash(userId, category.getCategoryId());
511                    }
512            }
513    
514            @Override
515            public MBCategory moveCategory(
516                            long categoryId, long parentCategoryId,
517                            boolean mergeWithParentCategory)
518                    throws PortalException, SystemException {
519    
520                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
521                            categoryId);
522    
523                    parentCategoryId = getParentCategoryId(category, parentCategoryId);
524    
525                    if (mergeWithParentCategory &&
526                            (categoryId != parentCategoryId) &&
527                            (parentCategoryId !=
528                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
529                            (parentCategoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
530    
531                            mergeCategories(category, parentCategoryId);
532    
533                            return category;
534                    }
535    
536                    category.setParentCategoryId(parentCategoryId);
537    
538                    return mbCategoryPersistence.update(category);
539            }
540    
541            @Override
542            public MBCategory moveCategoryFromTrash(
543                            long userId, long categoryId, long newCategoryId)
544                    throws PortalException, SystemException {
545    
546                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
547                            categoryId);
548    
549                    try {
550                            trashEntryLocalService.getEntry(
551                                    MBCategory.class.getName(), categoryId);
552    
553                            restoreCategoryFromTrash(userId, categoryId);
554                    }
555                    catch (NoSuchEntryException nsee) {
556    
557                            // Category
558    
559                            updateStatus(userId, categoryId, category.getStatus());
560    
561                            // Categories and threads
562    
563                            User user = userPersistence.findByPrimaryKey(userId);
564    
565                            List<Object> categoriesAndThreads = getCategoriesAndThreads(
566                                    category.getGroupId(), categoryId);
567    
568                            TrashEntry trashEntry = category.getTrashEntry();
569    
570                            restoreDependentFromTrash(
571                                    user, categoriesAndThreads, trashEntry.getEntryId());
572                    }
573    
574                    return moveCategory(categoryId, newCategoryId, false);
575            }
576    
577            @Override
578            public MBCategory moveCategoryToTrash(long userId, long categoryId)
579                    throws PortalException, SystemException {
580    
581                    // Category
582    
583                    MBCategory category = updateStatus(
584                            userId, categoryId, WorkflowConstants.STATUS_IN_TRASH);
585    
586                    // Trash
587    
588                    TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
589                            userId, category.getGroupId(), MBCategory.class.getName(),
590                            categoryId, category.getUuid(), null,
591                            WorkflowConstants.STATUS_APPROVED, null, null);
592    
593                    // Categories and threads
594    
595                    User user = userPersistence.findByPrimaryKey(userId);
596    
597                    List<Object> categoriesAndThreads = getCategoriesAndThreads(
598                            category.getGroupId(), categoryId);
599    
600                    moveDependentsToTrash(
601                            user, categoriesAndThreads, trashEntry.getEntryId());
602    
603                    return category;
604            }
605    
606            @Override
607            public void restoreCategoryFromTrash(long userId, long categoryId)
608                    throws PortalException, SystemException {
609    
610                    // Category
611    
612                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
613                            MBCategory.class.getName(), categoryId);
614    
615                    MBCategory category = updateStatus(
616                            userId, categoryId, WorkflowConstants.STATUS_APPROVED);
617    
618                    // Categories and threads
619    
620                    User user = userPersistence.findByPrimaryKey(userId);
621    
622                    List<Object> categoriesAndThreads = getCategoriesAndThreads(
623                            category.getGroupId(), categoryId);
624    
625                    restoreDependentFromTrash(
626                            user, categoriesAndThreads, trashEntry.getEntryId());
627    
628                    // Trash
629    
630                    trashEntryLocalService.deleteEntry(trashEntry.getEntryId());
631            }
632    
633            @Override
634            public void subscribeCategory(long userId, long groupId, long categoryId)
635                    throws PortalException, SystemException {
636    
637                    if (categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
638                            categoryId = groupId;
639                    }
640    
641                    subscriptionLocalService.addSubscription(
642                            userId, groupId, MBCategory.class.getName(), categoryId);
643            }
644    
645            @Override
646            public void unsubscribeCategory(long userId, long groupId, long categoryId)
647                    throws PortalException, SystemException {
648    
649                    if (categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
650                            categoryId = groupId;
651                    }
652    
653                    subscriptionLocalService.deleteSubscription(
654                            userId, MBCategory.class.getName(), categoryId);
655            }
656    
657            @Override
658            public MBCategory updateCategory(
659                            long categoryId, long parentCategoryId, String name,
660                            String description, String displayStyle, String emailAddress,
661                            String inProtocol, String inServerName, int inServerPort,
662                            boolean inUseSSL, String inUserName, String inPassword,
663                            int inReadInterval, String outEmailAddress, boolean outCustom,
664                            String outServerName, int outServerPort, boolean outUseSSL,
665                            String outUserName, String outPassword, boolean allowAnonymous,
666                            boolean mailingListActive, boolean mergeWithParentCategory,
667                            ServiceContext serviceContext)
668                    throws PortalException, SystemException {
669    
670                    // Merge categories
671    
672                    if ((categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) ||
673                            (categoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
674    
675                            return null;
676                    }
677    
678                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
679                            categoryId);
680    
681                    parentCategoryId = getParentCategoryId(category, parentCategoryId);
682    
683                    if (mergeWithParentCategory &&
684                            (categoryId != parentCategoryId) &&
685                            (parentCategoryId !=
686                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
687                            (parentCategoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
688    
689                            mergeCategories(category, parentCategoryId);
690    
691                            return category;
692                    }
693    
694                    // Category
695    
696                    validate(name);
697    
698                    category.setModifiedDate(serviceContext.getModifiedDate(null));
699                    category.setParentCategoryId(parentCategoryId);
700                    category.setName(name);
701                    category.setDescription(description);
702    
703                    if (!displayStyle.equals(category.getDisplayStyle())) {
704                            category.setDisplayStyle(displayStyle);
705    
706                            updateChildCategoriesDisplayStyle(category, displayStyle);
707                    }
708    
709                    category.setExpandoBridgeAttributes(serviceContext);
710    
711                    mbCategoryPersistence.update(category);
712    
713                    // Mailing list
714    
715                    MBMailingList mailingList = mbMailingListPersistence.fetchByG_C(
716                            category.getGroupId(), category.getCategoryId());
717    
718                    if (mailingList != null) {
719                            mbMailingListLocalService.updateMailingList(
720                                    mailingList.getMailingListId(), emailAddress, inProtocol,
721                                    inServerName, inServerPort, inUseSSL, inUserName, inPassword,
722                                    inReadInterval, outEmailAddress, outCustom, outServerName,
723                                    outServerPort, outUseSSL, outUserName, outPassword,
724                                    allowAnonymous, mailingListActive, serviceContext);
725                    }
726                    else {
727                            mbMailingListLocalService.addMailingList(
728                                    category.getUserId(), category.getGroupId(),
729                                    category.getCategoryId(), emailAddress, inProtocol,
730                                    inServerName, inServerPort, inUseSSL, inUserName, inPassword,
731                                    inReadInterval, outEmailAddress, outCustom, outServerName,
732                                    outServerPort, outUseSSL, outUserName, outPassword,
733                                    allowAnonymous, mailingListActive, serviceContext);
734                    }
735    
736                    return category;
737            }
738    
739            @Override
740            public MBCategory updateStatus(long userId, long categoryId, int status)
741                    throws PortalException, SystemException {
742    
743                    // Category
744    
745                    User user = userPersistence.findByPrimaryKey(userId);
746    
747                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
748                            categoryId);
749    
750                    category.setStatus(status);
751                    category.setStatusByUserId(user.getUserId());
752                    category.setStatusByUserName(user.getFullName());
753                    category.setStatusDate(new Date());
754    
755                    mbCategoryPersistence.update(category);
756    
757                    return category;
758            }
759    
760            protected long getParentCategoryId(long groupId, long parentCategoryId)
761                    throws SystemException {
762    
763                    if ((parentCategoryId !=
764                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
765                            (parentCategoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
766    
767                            MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
768                                    parentCategoryId);
769    
770                            if ((parentCategory == null) ||
771                                    (groupId != parentCategory.getGroupId())) {
772    
773                                    parentCategoryId =
774                                            MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
775                            }
776                    }
777    
778                    return parentCategoryId;
779            }
780    
781            protected long getParentCategoryId(
782                            MBCategory category, long parentCategoryId)
783                    throws SystemException {
784    
785                    if ((parentCategoryId ==
786                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) ||
787                            (parentCategoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
788    
789                            return parentCategoryId;
790                    }
791    
792                    if (category.getCategoryId() == parentCategoryId) {
793                            return category.getParentCategoryId();
794                    }
795    
796                    MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
797                            parentCategoryId);
798    
799                    if ((parentCategory == null) ||
800                            (category.getGroupId() != parentCategory.getGroupId())) {
801    
802                            return category.getParentCategoryId();
803                    }
804    
805                    List<Long> subcategoryIds = new ArrayList<Long>();
806    
807                    getSubcategoryIds(
808                            subcategoryIds, category.getGroupId(), category.getCategoryId());
809    
810                    if (subcategoryIds.contains(parentCategoryId)) {
811                            return category.getParentCategoryId();
812                    }
813    
814                    return parentCategoryId;
815            }
816    
817            protected void mergeCategories(MBCategory fromCategory, long toCategoryId)
818                    throws PortalException, SystemException {
819    
820                    if ((toCategoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) ||
821                            (toCategoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
822    
823                            return;
824                    }
825    
826                    List<MBCategory> categories = mbCategoryPersistence.findByG_P(
827                            fromCategory.getGroupId(), fromCategory.getCategoryId());
828    
829                    for (MBCategory category : categories) {
830                            mergeCategories(category, toCategoryId);
831                    }
832    
833                    List<MBThread> threads = mbThreadPersistence.findByG_C(
834                            fromCategory.getGroupId(), fromCategory.getCategoryId());
835    
836                    for (MBThread thread : threads) {
837    
838                            // Thread
839    
840                            thread.setCategoryId(toCategoryId);
841    
842                            mbThreadPersistence.update(thread);
843    
844                            List<MBMessage> messages = mbMessagePersistence.findByThreadId(
845                                    thread.getThreadId());
846    
847                            for (MBMessage message : messages) {
848    
849                                    // Message
850    
851                                    message.setCategoryId(toCategoryId);
852    
853                                    mbMessagePersistence.update(message);
854    
855                                    // Indexer
856    
857                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
858                                            MBMessage.class);
859    
860                                    indexer.reindex(message);
861                            }
862                    }
863    
864                    MBCategory toCategory = mbCategoryPersistence.findByPrimaryKey(
865                            toCategoryId);
866    
867                    toCategory.setThreadCount(
868                            fromCategory.getThreadCount() + toCategory.getThreadCount());
869                    toCategory.setMessageCount(
870                            fromCategory.getMessageCount() + toCategory.getMessageCount());
871    
872                    mbCategoryPersistence.update(toCategory);
873    
874                    deleteCategory(fromCategory);
875            }
876    
877            protected void moveDependentsToTrash(
878                            User user, List<Object> categoriesAndThreads, long trashEntryId)
879                    throws PortalException, SystemException {
880    
881                    for (Object object : categoriesAndThreads) {
882                            if (object instanceof MBThread) {
883    
884                                    // Thread
885    
886                                    MBThread thread = (MBThread)object;
887    
888                                    int oldStatus = thread.getStatus();
889    
890                                    if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
891                                            continue;
892                                    }
893    
894                                    thread.setStatus(WorkflowConstants.STATUS_IN_TRASH);
895    
896                                    mbThreadPersistence.update(thread);
897    
898                                    // Trash
899    
900                                    if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
901                                            trashVersionLocalService.addTrashVersion(
902                                                    trashEntryId, MBThread.class.getName(),
903                                                    thread.getThreadId(), oldStatus);
904                                    }
905    
906                                    // Threads
907    
908                                    mbThreadLocalService.moveDependentsToTrash(
909                                            user.getUserId(), thread.getThreadId(), trashEntryId);
910    
911                                    // Indexer
912    
913                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
914                                            MBThread.class);
915    
916                                    indexer.reindex(thread);
917                            }
918                            else if (object instanceof MBCategory) {
919    
920                                    // Category
921    
922                                    MBCategory category = (MBCategory)object;
923    
924                                    if (category.isInTrash()) {
925                                            continue;
926                                    }
927    
928                                    int oldStatus = category.getStatus();
929    
930                                    category.setStatus(WorkflowConstants.STATUS_IN_TRASH);
931    
932                                    mbCategoryPersistence.update(category);
933    
934                                    // Trash
935    
936                                    if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
937                                            trashVersionLocalService.addTrashVersion(
938                                                    trashEntryId, MBCategory.class.getName(),
939                                                    category.getCategoryId(), oldStatus);
940                                    }
941    
942                                    // Categories and threads
943    
944                                    moveDependentsToTrash(
945                                            user,
946                                            getCategoriesAndThreads(
947                                                    category.getGroupId(), category.getCategoryId()),
948                                            trashEntryId);
949                            }
950                    }
951            }
952    
953            protected void restoreDependentFromTrash(
954                            User user, List<Object> categoriesAndThreads, long trashEntryId)
955                    throws PortalException, SystemException {
956    
957                    for (Object object : categoriesAndThreads) {
958                            if (object instanceof MBThread) {
959    
960                                    // Thread
961    
962                                    MBThread thread = (MBThread)object;
963    
964                                    TrashEntry trashEntry = trashEntryLocalService.fetchEntry(
965                                            MBThread.class.getName(), thread.getThreadId());
966    
967                                    if (trashEntry != null) {
968                                            continue;
969                                    }
970    
971                                    TrashVersion trashVersion =
972                                            trashVersionLocalService.fetchVersion(
973                                                    trashEntryId, MBThread.class.getName(),
974                                                    thread.getThreadId());
975    
976                                    int oldStatus = WorkflowConstants.STATUS_APPROVED;
977    
978                                    if (trashVersion != null) {
979                                            oldStatus = trashVersion.getStatus();
980                                    }
981    
982                                    thread.setStatus(oldStatus);
983    
984                                    mbThreadPersistence.update(thread);
985    
986                                    // Threads
987    
988                                    mbThreadLocalService.restoreDependentsFromTrash(
989                                            user.getUserId(), thread.getThreadId(), trashEntryId);
990    
991                                    // Trash
992    
993                                    if (trashVersion != null) {
994                                            trashVersionLocalService.deleteTrashVersion(trashVersion);
995                                    }
996    
997                                    // Indexer
998    
999                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1000                                            MBThread.class);
1001    
1002                                    indexer.reindex(thread);
1003                            }
1004                            else if (object instanceof MBCategory) {
1005    
1006                                    // Category
1007    
1008                                    MBCategory category = (MBCategory)object;
1009    
1010                                    TrashEntry trashEntry = trashEntryLocalService.fetchEntry(
1011                                            MBCategory.class.getName(), category.getCategoryId());
1012    
1013                                    if (trashEntry != null) {
1014                                            continue;
1015                                    }
1016    
1017                                    TrashVersion trashVersion =
1018                                            trashVersionLocalService.fetchVersion(
1019                                                    trashEntryId, MBCategory.class.getName(),
1020                                                    category.getCategoryId());
1021    
1022                                    int oldStatus = WorkflowConstants.STATUS_APPROVED;
1023    
1024                                    if (trashVersion != null) {
1025                                            oldStatus = trashVersion.getStatus();
1026                                    }
1027    
1028                                    category.setStatus(oldStatus);
1029    
1030                                    mbCategoryPersistence.update(category);
1031    
1032                                    // Categories and threads
1033    
1034                                    restoreDependentFromTrash(
1035                                            user,
1036                                            getCategoriesAndThreads(
1037                                                    category.getGroupId(), category.getCategoryId()),
1038                                            trashEntryId);
1039    
1040                                    // Trash
1041    
1042                                    if (trashVersion != null) {
1043                                            trashVersionLocalService.deleteTrashVersion(trashVersion);
1044                                    }
1045                            }
1046                    }
1047            }
1048    
1049            protected void updateChildCategoriesDisplayStyle(
1050                            MBCategory category, String displayStyle)
1051                    throws PortalException, SystemException {
1052    
1053                    List<MBCategory> categories = getCategories(
1054                            category.getGroupId(), category.getCategoryId(), QueryUtil.ALL_POS,
1055                            QueryUtil.ALL_POS);
1056    
1057                    for (MBCategory curCategory : categories) {
1058                            updateChildCategoriesDisplayStyle(curCategory, displayStyle);
1059    
1060                            curCategory.setDisplayStyle(displayStyle);
1061    
1062                            mbCategoryPersistence.update(curCategory);
1063                    }
1064            }
1065    
1066            protected void validate(String name) throws PortalException {
1067                    if (Validator.isNull(name)) {
1068                            throw new CategoryNameException();
1069                    }
1070            }
1071    
1072    }