001    /**
002     * Copyright (c) 2000-2010 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.documentlibrary.DuplicateDirectoryException;
018    import com.liferay.documentlibrary.NoSuchDirectoryException;
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.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.workflow.WorkflowConstants;
026    import com.liferay.portal.model.CompanyConstants;
027    import com.liferay.portal.model.GroupConstants;
028    import com.liferay.portal.model.ResourceConstants;
029    import com.liferay.portal.service.ServiceContext;
030    import com.liferay.portlet.messageboards.SplitThreadException;
031    import com.liferay.portlet.messageboards.model.MBCategory;
032    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
033    import com.liferay.portlet.messageboards.model.MBMessage;
034    import com.liferay.portlet.messageboards.model.MBMessageFlag;
035    import com.liferay.portlet.messageboards.model.MBMessageFlagConstants;
036    import com.liferay.portlet.messageboards.model.MBThread;
037    import com.liferay.portlet.messageboards.model.MBThreadConstants;
038    import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl;
039    
040    import java.util.ArrayList;
041    import java.util.List;
042    
043    /**
044     * @author Brian Wing Shun Chan
045     */
046    public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl {
047    
048            public void deleteThread(long threadId)
049                    throws PortalException, SystemException {
050    
051                    MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
052    
053                    deleteThread(thread);
054            }
055    
056            public void deleteThread(MBThread thread)
057                    throws PortalException, SystemException {
058    
059                    MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
060                            thread.getRootMessageId());
061    
062                    // Indexer
063    
064                    Indexer indexer = IndexerRegistryUtil.getIndexer(MBMessage.class);
065    
066                    indexer.delete(thread);
067    
068                    // Attachments
069    
070                    long companyId = rootMessage.getCompanyId();
071                    String portletId = CompanyConstants.SYSTEM_STRING;
072                    long repositoryId = CompanyConstants.SYSTEM;
073                    String dirName = thread.getAttachmentsDir();
074    
075                    try {
076                            dlService.deleteDirectory(
077                                    companyId, portletId, repositoryId, dirName);
078                    }
079                    catch (NoSuchDirectoryException nsde) {
080                    }
081    
082                    // Messages
083    
084                    List<MBMessage> messages = mbMessagePersistence.findByThreadId(
085                            thread.getThreadId());
086    
087                    for (MBMessage message : messages) {
088    
089                            // Social
090    
091                            socialActivityLocalService.deleteActivities(
092                                    MBMessage.class.getName(), message.getMessageId());
093    
094                            // Ratings
095    
096                            ratingsStatsLocalService.deleteStats(
097                                    MBMessage.class.getName(), message.getMessageId());
098    
099                            // Asset
100    
101                            assetEntryLocalService.deleteEntry(
102                                    MBMessage.class.getName(), message.getMessageId());
103    
104                            // Statistics
105    
106                            if (!message.isDiscussion()) {
107                                    mbStatsUserLocalService.updateStatsUser(
108                                            message.getGroupId(), message.getUserId());
109                            }
110    
111                            // Message flags
112    
113                            mbMessageFlagPersistence.removeByMessageId(message.getMessageId());
114    
115                            // Resources
116    
117                            if (!message.isDiscussion()) {
118                                    resourceLocalService.deleteResource(
119                                            message.getCompanyId(), MBMessage.class.getName(),
120                                            ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
121                            }
122    
123                            // Message
124    
125                            mbMessagePersistence.remove(message);
126    
127                            // Workflow
128    
129                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
130                                    message.getCompanyId(), message.getGroupId(),
131                                    message.getWorkflowClassName(), message.getMessageId());
132                    }
133    
134                    // Category
135    
136                    if ((rootMessage.getCategoryId() !=
137                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
138                            (rootMessage.getCategoryId() !=
139                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
140    
141                            MBCategory category = mbCategoryPersistence.findByPrimaryKey(
142                                    thread.getCategoryId());
143    
144                            category.setThreadCount(category.getThreadCount() - 1);
145                            category.setMessageCount(
146                                    category.getMessageCount() - messages.size());
147    
148                            mbCategoryPersistence.update(category, false);
149                    }
150    
151                    // Thread
152    
153                    mbThreadPersistence.remove(thread);
154            }
155    
156            public void deleteThreads(long groupId, long categoryId)
157                    throws PortalException, SystemException {
158    
159                    List<MBThread> threads = mbThreadPersistence.findByG_C(
160                            groupId, categoryId);
161    
162                    for (MBThread thread : threads) {
163                            deleteThread(thread);
164                    }
165            }
166    
167            public int getCategoryThreadsCount(
168                            long groupId, long categoryId, int status)
169                    throws SystemException {
170    
171                    if (status == WorkflowConstants.STATUS_ANY) {
172                            return mbThreadPersistence.countByG_C(groupId, categoryId);
173                    }
174                    else {
175                            return mbThreadPersistence.countByG_C_S(
176                                    groupId, categoryId, status);
177                    }
178            }
179    
180            public List<MBThread> getGroupThreads(
181                            long groupId, int status, int start, int end)
182                    throws SystemException {
183    
184                    if (status == WorkflowConstants.STATUS_ANY) {
185                            return mbThreadPersistence.findByG_NotC(
186                                    groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, start,
187                                    end);
188                    }
189                    else {
190                            return mbThreadPersistence.findByG_NotC_S(
191                                    groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status,
192                                    start, end);
193                    }
194            }
195    
196            public List<MBThread> getGroupThreads(
197                            long groupId, long userId, int status, boolean subscribed,
198                            boolean includeAnonymous, int start, int end)
199                    throws PortalException, SystemException {
200    
201                    if (userId <= 0) {
202                            if (status == WorkflowConstants.STATUS_ANY) {
203                                    return mbThreadPersistence.findByG_NotC(
204                                            groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, start,
205                                            end);
206                            }
207                            else {
208                                    return mbThreadPersistence.findByG_NotC_S(
209                                            groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status,
210                                            start, end);
211                            }
212                    }
213                    else {
214                            if (subscribed) {
215                                    return mbThreadFinder.findByS_G_U_C_S(
216                                            groupId, userId, null, status, start, end);
217                            }
218                            else {
219                                    List<Long> threadIds = null;
220    
221                                    if (includeAnonymous) {
222                                            threadIds = mbMessageFinder.findByG_U_C_S(
223                                                    groupId, userId, null, status, start, end);
224                                    }
225                                    else {
226                                            threadIds = mbMessageFinder.findByG_U_C_A_S(
227                                                    groupId, userId, null, false, status, start, end);
228                                    }
229    
230                                    List<MBThread> threads = new ArrayList<MBThread>(
231                                            threadIds.size());
232    
233                                    for (long threadId : threadIds) {
234                                            MBThread thread = mbThreadPersistence.findByPrimaryKey(
235                                                    threadId);
236    
237                                            threads.add(thread);
238                                    }
239    
240                                    return threads;
241                            }
242                    }
243            }
244    
245            public List<MBThread> getGroupThreads(
246                            long groupId, long userId, int status, boolean subscribed,
247                            int start, int end)
248                    throws PortalException, SystemException {
249    
250                    return getGroupThreads(
251                            groupId, userId, status, subscribed, true, start, end);
252            }
253    
254            public List<MBThread> getGroupThreads(
255                            long groupId, long userId, int status, int start, int end)
256                    throws PortalException, SystemException {
257    
258                    return getGroupThreads(groupId, userId, status, false, start, end);
259            }
260    
261            public int getGroupThreadsCount(long groupId, int status)
262                    throws SystemException {
263    
264                    if (status == WorkflowConstants.STATUS_ANY) {
265                            return mbThreadPersistence.countByG_NotC(
266                                    groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID);
267                    }
268                    else {
269                            return mbThreadPersistence.countByG_NotC_S(
270                                    groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status);
271                    }
272            }
273    
274            public int getGroupThreadsCount(long groupId, long userId, int status)
275                    throws SystemException {
276    
277                    return getGroupThreadsCount(groupId, userId, status, false);
278            }
279    
280            public int getGroupThreadsCount(
281                            long groupId, long userId, int status, boolean subscribed)
282                    throws SystemException {
283    
284                    return getGroupThreadsCount(groupId, userId, status, subscribed, true);
285            }
286    
287            public int getGroupThreadsCount(
288                            long groupId, long userId, int status, boolean subscribed,
289                            boolean includeAnonymous)
290                    throws SystemException {
291    
292                    if (userId <= 0) {
293                            if (status == WorkflowConstants.STATUS_ANY) {
294                                    return mbThreadPersistence.countByG_NotC(
295                                            groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID);
296                            }
297                            else {
298                                    return mbThreadPersistence.countByG_NotC_S(
299                                            groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID,
300                                            status);
301                            }
302                    }
303                    else {
304                            if (subscribed) {
305                                    return mbThreadFinder.countByS_G_U_C_S(
306                                            groupId, userId, null, status);
307                            }
308                            else {
309                                    if (includeAnonymous) {
310                                            return mbMessageFinder.countByG_U_C_S(
311                                                    groupId, userId, null, status);
312                                    }
313                                    else {
314                                            return mbMessageFinder.countByG_U_C_A_S(
315                                                    groupId, userId, null, false, status);
316                                    }
317                            }
318                    }
319            }
320    
321            public List<MBThread> getPriorityThreads(long categoryId, double priority)
322                    throws PortalException, SystemException {
323    
324                    return getPriorityThreads(categoryId, priority, false);
325            }
326    
327            public List<MBThread> getPriorityThreads(
328                            long categoryId, double priority, boolean inherit)
329                    throws PortalException, SystemException {
330    
331                    if (!inherit) {
332                            return mbThreadPersistence.findByC_P(categoryId, priority);
333                    }
334    
335                    List<MBThread> threads = new ArrayList<MBThread>();
336    
337                    while ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
338                               (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
339    
340                            threads.addAll(
341                                    0, mbThreadPersistence.findByC_P(categoryId, priority));
342    
343                            MBCategory category = mbCategoryPersistence.findByPrimaryKey(
344                                    categoryId);
345    
346                            categoryId = category.getParentCategoryId();
347                    }
348    
349                    return threads;
350            }
351    
352            public MBThread getThread(long threadId)
353                    throws PortalException, SystemException {
354    
355                    return mbThreadPersistence.findByPrimaryKey(threadId);
356            }
357    
358            public List<MBThread> getThreads(
359                            long groupId, long categoryId, int status, int start, int end)
360                    throws SystemException {
361    
362                    if (status == WorkflowConstants.STATUS_ANY) {
363                            return mbThreadPersistence.findByG_C(
364                                    groupId, categoryId, start, end);
365                    }
366                    else {
367                            return mbThreadPersistence.findByG_C_S(
368                                    groupId, categoryId, status, start, end);
369                    }
370            }
371    
372            public int getThreadsCount(long groupId, long categoryId, int status)
373                    throws SystemException {
374    
375                    if (status == WorkflowConstants.STATUS_ANY) {
376                            return mbThreadPersistence.countByG_C(groupId, categoryId);
377                    }
378                    else {
379                            return mbThreadPersistence.countByG_C_S(
380                                    groupId, categoryId, status);
381                    }
382            }
383    
384            public MBThread moveThread(long groupId, long categoryId, long threadId)
385                    throws PortalException, SystemException {
386    
387                    MBThread thread = mbThreadPersistence.findByPrimaryKey(
388                            threadId);
389    
390                    long oldCategoryId = thread.getCategoryId();
391    
392                    MBCategory oldCategory = null;
393    
394                    if (oldCategoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
395                            oldCategory = mbCategoryPersistence.findByPrimaryKey(
396                                    oldCategoryId);
397                    }
398    
399                    MBCategory category = null;
400    
401                    if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
402                            category = mbCategoryPersistence.findByPrimaryKey(
403                                    categoryId);
404                    }
405    
406                    // Messages
407    
408                    List<MBMessage> messages = mbMessagePersistence.findByG_C_T(
409                            groupId, oldCategoryId, thread.getThreadId());
410    
411                    for (MBMessage message : messages) {
412                            message.setCategoryId(categoryId);
413    
414                            mbMessagePersistence.update(message, false);
415    
416                            // Indexer
417    
418                            if (!message.isDiscussion()) {
419                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
420                                            MBMessage.class);
421    
422                                    indexer.reindex(message);
423                            }
424                    }
425    
426                    // Thread
427    
428                    thread.setCategoryId(categoryId);
429    
430                    mbThreadPersistence.update(thread, false);
431    
432                    // Category
433    
434                    if (oldCategory != null) {
435                            oldCategory.setThreadCount(oldCategory.getThreadCount() - 1);
436                            oldCategory.setMessageCount(
437                                    oldCategory.getMessageCount() - messages.size());
438    
439                            mbCategoryPersistence.update(oldCategory, false);
440                    }
441    
442                    if (category != null) {
443                            category.setThreadCount(category.getThreadCount() + 1);
444                            category.setMessageCount(
445                                    category.getMessageCount() + messages.size());
446    
447                            mbCategoryPersistence.update(category, false);
448                    }
449    
450                    return thread;
451            }
452    
453            public MBThread splitThread(long messageId, ServiceContext serviceContext)
454                    throws PortalException, SystemException {
455    
456                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
457    
458                    if (message.isRoot()) {
459                            throw new SplitThreadException();
460                    }
461    
462                    MBCategory category = message.getCategory();
463                    MBThread oldThread = message.getThread();
464                    MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
465                            oldThread.getRootMessageId());
466                    String oldAttachmentsDir = message.getAttachmentsDir();
467    
468                    // Message flags
469    
470                    mbMessageFlagLocalService.deleteAnswerFlags(
471                            oldThread.getThreadId(), message.getMessageId());
472    
473                    int count = mbMessageFlagPersistence.countByT_F(
474                            oldThread.getThreadId(), MBMessageFlagConstants.ANSWER_FLAG);
475    
476                    if (count == 1) {
477                            MBMessageFlag messageFlag = mbMessageFlagPersistence.fetchByU_M_F(
478                                    rootMessage.getUserId(), rootMessage.getMessageId(),
479                                    MBMessageFlagConstants.ANSWER_FLAG);
480    
481                            messageFlag.setFlag(MBMessageFlagConstants.QUESTION_FLAG);
482    
483                            mbMessageFlagPersistence.update(messageFlag, false);
484                    }
485    
486                    // Create new thread
487    
488                    MBThread thread = addThread(message.getCategoryId(), message);
489    
490                    // Update message
491    
492                    message.setThreadId(thread.getThreadId());
493                    message.setRootMessageId(thread.getRootMessageId());
494                    message.setParentMessageId(0);
495                    message.setAttachmentsDir(null);
496    
497                    mbMessagePersistence.update(message, false);
498    
499                    // Attachments
500    
501                    moveAttachmentsFromOldThread(message, oldAttachmentsDir);
502    
503                    // Indexer
504    
505                    if (!message.isDiscussion()) {
506                            Indexer indexer = IndexerRegistryUtil.getIndexer(MBMessage.class);
507    
508                            indexer.reindex(message);
509                    }
510    
511                    // Update children
512    
513                    int messagesMoved = 1;
514    
515                    messagesMoved += moveChildrenMessages(
516                            message, category, oldThread.getThreadId());
517    
518                    // Update new thread
519    
520                    thread.setMessageCount(messagesMoved);
521    
522                    mbThreadPersistence.update(thread, false);
523    
524                    // Update old thread
525    
526                    oldThread.setMessageCount(oldThread.getMessageCount() - messagesMoved);
527    
528                    mbThreadPersistence.update(oldThread, false);
529    
530                    // Category
531    
532                    if ((message.getCategoryId() !=
533                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
534                            (message.getCategoryId() !=
535                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
536    
537                            category.setThreadCount(category.getThreadCount() + 1);
538    
539                            mbCategoryPersistence.update(category, false);
540                    }
541    
542                    return thread;
543            }
544    
545            public MBThread updateThread(long threadId, int viewCount)
546                    throws PortalException, SystemException {
547    
548                    MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
549    
550                    thread.setViewCount(viewCount);
551    
552                    mbThreadPersistence.update(thread, false);
553    
554                    return thread;
555            }
556    
557            protected MBThread addThread(long categoryId, MBMessage message)
558                    throws SystemException {
559    
560                    long threadId = counterLocalService.increment();
561    
562                    MBThread thread = mbThreadPersistence.create(threadId);
563    
564                    thread.setGroupId(message.getGroupId());
565                    thread.setCategoryId(categoryId);
566                    thread.setRootMessageId(message.getMessageId());
567                    thread.setStatus(message.getStatus());
568                    thread.setStatusByUserId(message.getStatusByUserId());
569                    thread.setStatusByUserName(message.getStatusByUserName());
570                    thread.setStatusDate(message.getStatusDate());
571    
572                    thread.setMessageCount(thread.getMessageCount() + 1);
573    
574                    if (message.isAnonymous()) {
575                            thread.setLastPostByUserId(0);
576                    }
577                    else {
578                            thread.setLastPostByUserId(message.getUserId());
579                    }
580    
581                    thread.setLastPostDate(message.getCreateDate());
582    
583                    if (message.getPriority() != MBThreadConstants.PRIORITY_NOT_GIVEN) {
584                            thread.setPriority(message.getPriority());
585                    }
586    
587                    mbThreadPersistence.update(thread, false);
588    
589                    return thread;
590            }
591    
592            protected void moveAttachmentsFromOldThread(
593                            MBMessage message, String oldAttachmentsDir)
594                    throws PortalException, SystemException {
595    
596                    if (!message.getAttachments()) {
597                            return;
598                    }
599    
600                    long companyId = message.getCompanyId();
601                    String portletId = CompanyConstants.SYSTEM_STRING;
602                    long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
603                    long repositoryId = CompanyConstants.SYSTEM;
604                    String newAttachmentsDir = message.getAttachmentsDir();
605    
606                    try {
607                            dlService.addDirectory(companyId, repositoryId, newAttachmentsDir);
608                    }
609                    catch (DuplicateDirectoryException dde) {
610                    }
611    
612                    String[] fileNames = dlService.getFileNames(
613                            companyId, repositoryId, oldAttachmentsDir);
614    
615                    for (String fileName : fileNames) {
616                            String name = StringUtil.extractLast(fileName, StringPool.SLASH);
617                            byte[] fileBytes = dlService.getFile(
618                                    companyId, repositoryId, fileName);
619    
620                            dlService.addFile(
621                                    companyId, portletId, groupId, repositoryId,
622                                    newAttachmentsDir + "/" + name, 0, StringPool.BLANK,
623                                    message.getModifiedDate(), new ServiceContext(), fileBytes);
624    
625                            dlService.deleteFile(companyId, portletId, repositoryId, fileName);
626                    }
627    
628                    try {
629                            dlService.deleteDirectory(
630                                    companyId, portletId, repositoryId, oldAttachmentsDir);
631                    }
632                    catch (NoSuchDirectoryException nsde) {
633                    }
634            }
635    
636            protected int moveChildrenMessages(
637                            MBMessage parentMessage, MBCategory category, long oldThreadId)
638                    throws SystemException, PortalException {
639    
640                    int messagesMoved = 0;
641    
642                    List<MBMessage> messages = mbMessagePersistence.findByT_P(
643                            oldThreadId, parentMessage.getMessageId());
644    
645                    for (MBMessage message : messages) {
646                            String oldAttachmentsDir = message.getAttachmentsDir();
647    
648                            message.setCategoryId(parentMessage.getCategoryId());
649                            message.setThreadId(parentMessage.getThreadId());
650                            message.setRootMessageId(parentMessage.getRootMessageId());
651                            message.setAttachmentsDir(null);
652    
653                            mbMessagePersistence.update(message, false);
654    
655                            moveAttachmentsFromOldThread(message, oldAttachmentsDir);
656    
657                            if (!message.isDiscussion()) {
658                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
659                                            MBMessage.class);
660    
661                                    indexer.reindex(message);
662                            }
663    
664                            messagesMoved++;
665    
666                            messagesMoved += moveChildrenMessages(
667                                    message, category, oldThreadId);
668                    }
669    
670                    return messagesMoved;
671            }
672    
673    }