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