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