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