1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.messageboards.service.impl;
16  
17  import com.liferay.documentlibrary.DuplicateDirectoryException;
18  import com.liferay.documentlibrary.NoSuchDirectoryException;
19  import com.liferay.portal.kernel.exception.PortalException;
20  import com.liferay.portal.kernel.exception.SystemException;
21  import com.liferay.portal.kernel.search.Indexer;
22  import com.liferay.portal.kernel.search.IndexerRegistryUtil;
23  import com.liferay.portal.kernel.util.StringPool;
24  import com.liferay.portal.kernel.util.StringUtil;
25  import com.liferay.portal.kernel.workflow.WorkflowConstants;
26  import com.liferay.portal.model.CompanyConstants;
27  import com.liferay.portal.model.GroupConstants;
28  import com.liferay.portal.model.ResourceConstants;
29  import com.liferay.portal.service.ServiceContext;
30  import com.liferay.portlet.messageboards.SplitThreadException;
31  import com.liferay.portlet.messageboards.model.MBCategory;
32  import com.liferay.portlet.messageboards.model.MBCategoryConstants;
33  import com.liferay.portlet.messageboards.model.MBMessage;
34  import com.liferay.portlet.messageboards.model.MBMessageFlag;
35  import com.liferay.portlet.messageboards.model.MBMessageFlagConstants;
36  import com.liferay.portlet.messageboards.model.MBThread;
37  import com.liferay.portlet.messageboards.model.MBThreadConstants;
38  import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl;
39  
40  import java.util.ArrayList;
41  import java.util.List;
42  
43  /**
44   * <a href="MBThreadLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
45   *
46   * @author Brian Wing Shun Chan
47   */
48  public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl {
49  
50      public void deleteThread(long threadId)
51          throws PortalException, SystemException {
52  
53          MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
54  
55          deleteThread(thread);
56      }
57  
58      public void deleteThread(MBThread thread)
59          throws PortalException, SystemException {
60  
61          MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
62              thread.getRootMessageId());
63  
64          // Indexer
65  
66          Indexer indexer = IndexerRegistryUtil.getIndexer(MBMessage.class);
67  
68          indexer.delete(thread);
69  
70          // Attachments
71  
72          long companyId = rootMessage.getCompanyId();
73          String portletId = CompanyConstants.SYSTEM_STRING;
74          long repositoryId = CompanyConstants.SYSTEM;
75          String dirName = thread.getAttachmentsDir();
76  
77          try {
78              dlService.deleteDirectory(
79                  companyId, portletId, repositoryId, dirName);
80          }
81          catch (NoSuchDirectoryException nsde) {
82          }
83  
84          // Messages
85  
86          List<MBMessage> messages = mbMessagePersistence.findByThreadId(
87              thread.getThreadId());
88  
89          for (MBMessage message : messages) {
90  
91              // Social
92  
93              socialActivityLocalService.deleteActivities(
94                  MBMessage.class.getName(), message.getMessageId());
95  
96              // Ratings
97  
98              ratingsStatsLocalService.deleteStats(
99                  MBMessage.class.getName(), message.getMessageId());
100 
101             // Asset
102 
103             assetEntryLocalService.deleteEntry(
104                 MBMessage.class.getName(), message.getMessageId());
105 
106             // Statistics
107 
108             if (!message.isDiscussion()) {
109                 mbStatsUserLocalService.updateStatsUser(
110                     message.getGroupId(), message.getUserId());
111             }
112 
113             // Message flags
114 
115             mbMessageFlagPersistence.removeByMessageId(message.getMessageId());
116 
117             // Resources
118 
119             if (!message.isDiscussion()) {
120                 resourceLocalService.deleteResource(
121                     message.getCompanyId(), MBMessage.class.getName(),
122                     ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
123             }
124 
125             // Message
126 
127             mbMessagePersistence.remove(message);
128         }
129 
130         // Category
131 
132         if ((rootMessage.getCategoryId() !=
133                 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
134             (rootMessage.getCategoryId() !=
135                 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
136 
137             MBCategory category = mbCategoryPersistence.findByPrimaryKey(
138                 thread.getCategoryId());
139 
140             category.setThreadCount(category.getThreadCount() - 1);
141             category.setMessageCount(
142                 category.getMessageCount() - messages.size());
143 
144             mbCategoryPersistence.update(category, false);
145         }
146 
147         // Thread
148 
149         mbThreadPersistence.remove(thread);
150     }
151 
152     public void deleteThreads(long groupId, long categoryId)
153         throws PortalException, SystemException {
154 
155         List<MBThread> threads = mbThreadPersistence.findByG_C(
156             groupId, categoryId);
157 
158         for (MBThread thread : threads) {
159             deleteThread(thread);
160         }
161     }
162 
163     public int getCategoryThreadsCount(
164             long groupId, long categoryId, int status)
165         throws SystemException {
166 
167         if (status == WorkflowConstants.STATUS_ANY) {
168             return mbThreadPersistence.countByG_C(groupId, categoryId);
169         }
170         else {
171             return mbThreadPersistence.countByG_C_S(
172                 groupId, categoryId, status);
173         }
174     }
175 
176     public List<MBThread> getGroupThreads(
177             long groupId, int status, int start, int end)
178         throws SystemException {
179 
180         if (status == WorkflowConstants.STATUS_ANY) {
181             return mbThreadPersistence.findByGroupId(groupId, start, end);
182         }
183         else {
184             return mbThreadPersistence.findByG_S(groupId, status, start, end);
185         }
186     }
187 
188     public List<MBThread> getGroupThreads(
189             long groupId, long userId, int status, int start, int end)
190         throws PortalException, SystemException {
191 
192         return getGroupThreads(groupId, userId, status, false, start, end);
193     }
194 
195     public List<MBThread> getGroupThreads(
196             long groupId, long userId, int status, boolean subscribed,
197             int start, int end)
198         throws PortalException, SystemException {
199 
200         return getGroupThreads(
201             groupId, userId, status, subscribed, true, start, end);
202     }
203 
204     public List<MBThread> getGroupThreads(
205             long groupId, long userId, int status, boolean subscribed,
206             boolean includeAnonymous, int start, int end)
207         throws PortalException, SystemException {
208 
209         if (userId <= 0) {
210             if (status == WorkflowConstants.STATUS_ANY) {
211                 return mbThreadPersistence.findByGroupId(groupId, start, end);
212             }
213             else {
214                 return mbThreadPersistence.findByG_S(
215                     groupId, status, start, end);
216             }
217         }
218         else {
219             if (subscribed) {
220                 return mbThreadFinder.findByS_G_U_S(
221                     groupId, userId, status, start, end);
222             }
223             else {
224                 List<Long> threadIds = null;
225 
226                 if (includeAnonymous) {
227                     threadIds = mbMessageFinder.findByG_U_S(
228                         groupId, userId, status, start, end);
229                 }
230                 else {
231                     threadIds = mbMessageFinder.findByG_U_A_S(
232                         groupId, userId, false, status, start, end);
233                 }
234 
235                 List<MBThread> threads = new ArrayList<MBThread>(
236                     threadIds.size());
237 
238                 for (long threadId : threadIds) {
239                     MBThread thread = mbThreadPersistence.findByPrimaryKey(
240                         threadId);
241 
242                     threads.add(thread);
243                 }
244 
245                 return threads;
246             }
247         }
248     }
249 
250     public int getGroupThreadsCount(long groupId, int status)
251         throws SystemException {
252 
253         if (status == WorkflowConstants.STATUS_ANY) {
254             return mbThreadPersistence.countByGroupId(groupId);
255         }
256         else {
257             return mbThreadPersistence.countByG_S(groupId, status);
258         }
259     }
260 
261     public int getGroupThreadsCount(long groupId, long userId, int status)
262         throws SystemException {
263 
264         return getGroupThreadsCount(groupId, userId, status, false);
265     }
266 
267     public int getGroupThreadsCount(
268             long groupId, long userId, int status, boolean subscribed)
269         throws SystemException {
270 
271         return getGroupThreadsCount(groupId, userId, status, subscribed, true);
272     }
273 
274     public int getGroupThreadsCount(
275             long groupId, long userId, int status, boolean subscribed,
276             boolean includeAnonymous)
277         throws SystemException {
278 
279         if (userId <= 0) {
280             if (status == WorkflowConstants.STATUS_ANY) {
281                 return mbThreadPersistence.countByGroupId(groupId);
282             }
283             else {
284                 return mbThreadPersistence.countByG_S(groupId, status);
285             }
286         }
287         else {
288             if (subscribed) {
289                 return mbThreadFinder.countByS_G_U_S(groupId, userId, status);
290             }
291             else {
292                 if (includeAnonymous) {
293                     return mbMessageFinder.countByG_U_S(
294                         groupId, userId, status);
295                 }
296                 else {
297                     return mbMessageFinder.countByG_U_A_S(
298                         groupId, userId, false, status);
299                 }
300             }
301         }
302     }
303 
304     public List<MBThread> getPriorityThreads(long categoryId, double priority)
305         throws PortalException, SystemException {
306 
307         return getPriorityThreads(categoryId, priority, false);
308     }
309 
310     public List<MBThread> getPriorityThreads(
311             long categoryId, double priority, boolean inherit)
312         throws PortalException, SystemException {
313 
314         if (!inherit) {
315             return mbThreadPersistence.findByC_P(categoryId, priority);
316         }
317 
318         List<MBThread> threads = new ArrayList<MBThread>();
319 
320         while ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
321                (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
322 
323             threads.addAll(
324                 0, mbThreadPersistence.findByC_P(categoryId, priority));
325 
326             MBCategory category = mbCategoryPersistence.findByPrimaryKey(
327                 categoryId);
328 
329             categoryId = category.getParentCategoryId();
330         }
331 
332         return threads;
333     }
334 
335     public MBThread getThread(long threadId)
336         throws PortalException, SystemException {
337 
338         return mbThreadPersistence.findByPrimaryKey(threadId);
339     }
340 
341     public List<MBThread> getThreads(
342             long groupId, long categoryId, int status, int start, int end)
343         throws SystemException {
344 
345         if (status == WorkflowConstants.STATUS_ANY) {
346             return mbThreadPersistence.findByG_C(
347                 groupId, categoryId, start, end);
348         }
349         else {
350             return mbThreadPersistence.findByG_C_S(
351                 groupId, categoryId, status, start, end);
352         }
353     }
354 
355     public int getThreadsCount(long groupId, long categoryId, int status)
356         throws SystemException {
357 
358         if (status == WorkflowConstants.STATUS_ANY) {
359             return mbThreadPersistence.countByG_C(groupId, categoryId);
360         }
361         else {
362             return mbThreadPersistence.countByG_C_S(
363                 groupId, categoryId, status);
364         }
365     }
366 
367     public MBThread moveThread(long groupId, long categoryId, long threadId)
368         throws PortalException, SystemException {
369 
370         MBThread thread = mbThreadPersistence.findByPrimaryKey(
371             threadId);
372 
373         long oldCategoryId = thread.getCategoryId();
374 
375         MBCategory oldCategory = null;
376 
377         if (oldCategoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
378             oldCategory = mbCategoryPersistence.findByPrimaryKey(
379                 oldCategoryId);
380         }
381 
382         MBCategory category = null;
383 
384         if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
385             category = mbCategoryPersistence.findByPrimaryKey(
386                 categoryId);
387         }
388 
389         // Messages
390 
391         List<MBMessage> messages = mbMessagePersistence.findByG_C_T(
392             groupId, oldCategoryId, thread.getThreadId());
393 
394         for (MBMessage message : messages) {
395             message.setCategoryId(categoryId);
396 
397             mbMessagePersistence.update(message, false);
398 
399             // Indexer
400 
401             if (!message.isDiscussion()) {
402                 Indexer indexer = IndexerRegistryUtil.getIndexer(
403                     MBMessage.class);
404 
405                 indexer.reindex(message);
406             }
407         }
408 
409         // Thread
410 
411         thread.setCategoryId(categoryId);
412 
413         mbThreadPersistence.update(thread, false);
414 
415         // Category
416 
417         if (oldCategory != null) {
418             oldCategory.setThreadCount(oldCategory.getThreadCount() - 1);
419             oldCategory.setMessageCount(
420                 oldCategory.getMessageCount() - messages.size());
421 
422             mbCategoryPersistence.update(oldCategory, false);
423         }
424 
425         if (category != null) {
426             category.setThreadCount(category.getThreadCount() + 1);
427             category.setMessageCount(
428                 category.getMessageCount() + messages.size());
429 
430             mbCategoryPersistence.update(category, false);
431         }
432 
433         return thread;
434     }
435 
436     public MBThread splitThread(long messageId, ServiceContext serviceContext)
437         throws PortalException, SystemException {
438 
439         MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
440 
441         if (message.isRoot()) {
442             throw new SplitThreadException();
443         }
444 
445         MBCategory category = message.getCategory();
446         MBThread oldThread = message.getThread();
447         MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
448             oldThread.getRootMessageId());
449         String oldAttachmentsDir = message.getAttachmentsDir();
450 
451         // Message flags
452 
453         mbMessageFlagLocalService.deleteAnswerFlags(
454             oldThread.getThreadId(), message.getMessageId());
455 
456         int count = mbMessageFlagPersistence.countByT_F(
457             oldThread.getThreadId(), MBMessageFlagConstants.ANSWER_FLAG);
458 
459         if (count == 1) {
460             MBMessageFlag messageFlag = mbMessageFlagPersistence.fetchByU_M_F(
461                 rootMessage.getUserId(), rootMessage.getMessageId(),
462                 MBMessageFlagConstants.ANSWER_FLAG);
463 
464             messageFlag.setFlag(MBMessageFlagConstants.QUESTION_FLAG);
465 
466             mbMessageFlagPersistence.update(messageFlag, false);
467         }
468 
469         // Create new thread
470 
471         MBThread thread = addThread(message.getCategoryId(), message);
472 
473         // Update message
474 
475         message.setThreadId(thread.getThreadId());
476         message.setParentMessageId(0);
477         message.setAttachmentsDir(null);
478 
479         mbMessagePersistence.update(message, false);
480 
481         // Attachments
482 
483         moveAttachmentsFromOldThread(message, oldAttachmentsDir);
484 
485         // Indexer
486 
487         if (!message.isDiscussion()) {
488             Indexer indexer = IndexerRegistryUtil.getIndexer(MBMessage.class);
489 
490             indexer.reindex(message);
491         }
492 
493         // Update children
494 
495         int messagesMoved = 1;
496 
497         messagesMoved += moveChildrenMessages(
498             message, category, oldThread.getThreadId());
499 
500         // Update new thread
501 
502         thread.setMessageCount(messagesMoved);
503 
504         mbThreadPersistence.update(thread, false);
505 
506         // Update old thread
507 
508         oldThread.setMessageCount(oldThread.getMessageCount() - messagesMoved);
509 
510         mbThreadPersistence.update(oldThread, false);
511 
512         // Category
513 
514         category.setThreadCount(category.getThreadCount() + 1);
515 
516         mbCategoryPersistence.update(category, false);
517 
518         return thread;
519     }
520 
521     public MBThread updateThread(long threadId, int viewCount)
522         throws PortalException, SystemException {
523 
524         MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
525 
526         thread.setViewCount(viewCount);
527 
528         mbThreadPersistence.update(thread, false);
529 
530         return thread;
531     }
532 
533     protected MBThread addThread(long categoryId, MBMessage message)
534         throws SystemException {
535 
536         long threadId = counterLocalService.increment();
537 
538         MBThread thread = mbThreadPersistence.create(threadId);
539 
540         thread.setGroupId(message.getGroupId());
541         thread.setCategoryId(categoryId);
542         thread.setRootMessageId(message.getMessageId());
543         thread.setStatus(message.getStatus());
544         thread.setStatusByUserId(message.getStatusByUserId());
545         thread.setStatusByUserName(message.getStatusByUserName());
546         thread.setStatusDate(message.getStatusDate());
547 
548         thread.setMessageCount(thread.getMessageCount() + 1);
549 
550         if (message.isAnonymous()) {
551             thread.setLastPostByUserId(0);
552         }
553         else {
554             thread.setLastPostByUserId(message.getUserId());
555         }
556 
557         thread.setLastPostDate(message.getCreateDate());
558 
559         if (message.getPriority() != MBThreadConstants.PRIORITY_NOT_GIVEN) {
560             thread.setPriority(message.getPriority());
561         }
562 
563         mbThreadPersistence.update(thread, false);
564 
565         return thread;
566     }
567 
568     protected void moveAttachmentsFromOldThread(
569             MBMessage message, String oldAttachmentsDir)
570         throws PortalException, SystemException {
571 
572         if (!message.getAttachments()) {
573             return;
574         }
575 
576         long companyId = message.getCompanyId();
577         String portletId = CompanyConstants.SYSTEM_STRING;
578         long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
579         long repositoryId = CompanyConstants.SYSTEM;
580         String newAttachmentsDir = message.getAttachmentsDir();
581 
582         try {
583             dlService.addDirectory(companyId, repositoryId, newAttachmentsDir);
584         }
585         catch (DuplicateDirectoryException dde) {
586         }
587 
588         String[] fileNames = dlService.getFileNames(
589             companyId, repositoryId, oldAttachmentsDir);
590 
591         for (String fileName : fileNames) {
592             String name = StringUtil.extractLast(fileName, StringPool.SLASH);
593             byte[] fileBytes = dlService.getFile(
594                 companyId, repositoryId, fileName);
595 
596             dlService.addFile(
597                 companyId, portletId, groupId, repositoryId,
598                 newAttachmentsDir + "/" + name, 0, StringPool.BLANK,
599                 message.getModifiedDate(), new ServiceContext(), fileBytes);
600 
601             dlService.deleteFile(companyId, portletId, repositoryId, fileName);
602         }
603 
604         try {
605             dlService.deleteDirectory(
606                 companyId, portletId, repositoryId, oldAttachmentsDir);
607         }
608         catch (NoSuchDirectoryException nsde) {
609         }
610     }
611 
612     protected int moveChildrenMessages(
613             MBMessage parentMessage, MBCategory category, long oldThreadId)
614         throws SystemException, PortalException {
615 
616         int messagesMoved = 0;
617 
618         List<MBMessage> messages = mbMessagePersistence.findByT_P(
619             oldThreadId, parentMessage.getMessageId());
620 
621         for (MBMessage message : messages) {
622             String oldAttachmentsDir = message.getAttachmentsDir();
623 
624             message.setCategoryId(parentMessage.getCategoryId());
625             message.setThreadId(parentMessage.getThreadId());
626             message.setAttachmentsDir(null);
627 
628             mbMessagePersistence.update(message, false);
629 
630             moveAttachmentsFromOldThread(message, oldAttachmentsDir);
631 
632             if (!message.isDiscussion()) {
633                 Indexer indexer = IndexerRegistryUtil.getIndexer(
634                     MBMessage.class);
635 
636                 indexer.reindex(message);
637             }
638 
639             messagesMoved++;
640 
641             messagesMoved += moveChildrenMessages(
642                 message, category, oldThreadId);
643         }
644 
645         return messagesMoved;
646     }
647 
648 }