1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.messageboards.service.impl;
24  
25  import com.liferay.documentlibrary.DuplicateDirectoryException;
26  import com.liferay.documentlibrary.NoSuchDirectoryException;
27  import com.liferay.portal.PortalException;
28  import com.liferay.portal.SystemException;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.search.SearchException;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.model.CompanyConstants;
35  import com.liferay.portal.model.GroupConstants;
36  import com.liferay.portal.model.ResourceConstants;
37  import com.liferay.portal.theme.ThemeDisplay;
38  import com.liferay.portlet.messageboards.SplitThreadException;
39  import com.liferay.portlet.messageboards.model.MBCategory;
40  import com.liferay.portlet.messageboards.model.MBMessage;
41  import com.liferay.portlet.messageboards.model.MBThread;
42  import com.liferay.portlet.messageboards.model.impl.MBThreadImpl;
43  import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl;
44  import com.liferay.portlet.messageboards.util.Indexer;
45  
46  import java.rmi.RemoteException;
47  
48  import java.util.ArrayList;
49  import java.util.List;
50  
51  import javax.portlet.PortletPreferences;
52  
53  /**
54   * <a href="MBThreadLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
55   *
56   * @author Brian Wing Shun Chan
57   */
58  public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl {
59  
60      public void deleteThread(long threadId)
61          throws PortalException, SystemException {
62  
63          MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
64  
65          deleteThread(thread);
66      }
67  
68      public void deleteThread(MBThread thread)
69          throws PortalException, SystemException {
70  
71          MBCategory category = mbCategoryPersistence.findByPrimaryKey(
72              thread.getCategoryId());
73          MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
74              thread.getRootMessageId());
75  
76          // Indexer
77  
78          try {
79              Indexer.deleteMessages(
80                  rootMessage.getCompanyId(), thread.getThreadId());
81          }
82          catch (SearchException se) {
83              _log.error("Deleting index " + thread.getThreadId(), se);
84          }
85  
86          // Attachments
87  
88          long companyId = rootMessage.getCompanyId();
89          String portletId = CompanyConstants.SYSTEM_STRING;
90          long repositoryId = CompanyConstants.SYSTEM;
91          String dirName = thread.getAttachmentsDir();
92  
93          try {
94              dlService.deleteDirectory(
95                  companyId, portletId, repositoryId, dirName);
96          }
97          catch (NoSuchDirectoryException nsde) {
98          }
99          catch (RemoteException re) {
100             throw new SystemException(re);
101         }
102 
103         // Messages
104 
105         List<MBMessage> messages = mbMessagePersistence.findByThreadId(
106             thread.getThreadId());
107 
108         for (MBMessage message : messages) {
109 
110             // Tags
111 
112             tagsAssetLocalService.deleteAsset(
113                 MBMessage.class.getName(), message.getMessageId());
114 
115             // Social
116 
117             socialActivityLocalService.deleteActivities(
118                 MBMessage.class.getName(), message.getMessageId());
119 
120             // Ratings
121 
122             ratingsStatsLocalService.deleteStats(
123                 MBMessage.class.getName(), message.getMessageId());
124 
125             // Statistics
126 
127             if (!category.isDiscussion()) {
128                 mbStatsUserLocalService.updateStatsUser(
129                     message.getGroupId(), message.getUserId());
130             }
131 
132             // Message flags
133 
134             mbMessageFlagPersistence.removeByMessageId(message.getMessageId());
135 
136             // Resources
137 
138             if (!message.isDiscussion()) {
139                 resourceLocalService.deleteResource(
140                     message.getCompanyId(), MBMessage.class.getName(),
141                     ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
142             }
143 
144             // Message
145 
146             mbMessagePersistence.remove(message);
147         }
148 
149         // Category
150 
151         category.setThreadCount(category.getThreadCount() - 1);
152         category.setMessageCount(category.getMessageCount() - messages.size());
153 
154         mbCategoryPersistence.update(category, false);
155 
156         // Thread
157 
158         mbThreadPersistence.remove(thread);
159     }
160 
161     public void deleteThreads(long categoryId)
162         throws PortalException, SystemException {
163 
164         List<MBThread> threads = mbThreadPersistence.findByCategoryId(
165             categoryId);
166 
167         for (MBThread thread : threads) {
168             deleteThread(thread);
169         }
170     }
171 
172     /**
173      * @deprecated
174      */
175     public int getCategoriesThreadsCount(List<Long> categoryIds)
176         throws SystemException {
177 
178         return mbThreadFinder.countByCategoryIds(categoryIds);
179     }
180 
181     public int getCategoryThreadsCount(long categoryId) throws SystemException {
182         return mbThreadPersistence.countByCategoryId(categoryId);
183     }
184 
185     public List<MBThread> getGroupThreads(long groupId, int start, int end)
186         throws SystemException {
187 
188         return mbThreadPersistence.findByGroupId(groupId, start, end);
189     }
190 
191     public List<MBThread> getGroupThreads(
192             long groupId, long userId, int start, int end)
193         throws PortalException, SystemException {
194 
195         return getGroupThreads(groupId, userId, false, start, end);
196     }
197 
198     public List<MBThread> getGroupThreads(
199             long groupId, long userId, boolean subscribed, int start, int end)
200         throws PortalException, SystemException {
201 
202         return getGroupThreads(groupId, userId, subscribed, true, start, end);
203     }
204 
205     public List<MBThread> getGroupThreads(
206             long groupId, long userId, boolean subscribed,
207             boolean includeAnonymous, int start, int end)
208         throws PortalException, SystemException {
209 
210         if (userId <= 0) {
211             return mbThreadPersistence.findByGroupId(groupId, start, end);
212         }
213         else {
214             if (subscribed) {
215                 return mbThreadFinder.findByS_G_U(groupId, userId, start, end);
216             }
217             else {
218                 List<Long> threadIds = null;
219 
220                 if (includeAnonymous) {
221                     threadIds = mbMessageFinder.findByG_U(
222                         groupId, userId, start, end);
223                 }
224                 else {
225                     threadIds = mbMessageFinder.findByG_U_A(
226                         groupId, userId, false, 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 int getGroupThreadsCount(long groupId) throws SystemException {
245         return mbThreadPersistence.countByGroupId(groupId);
246     }
247 
248     public int getGroupThreadsCount(long groupId, long userId)
249         throws SystemException {
250 
251         return getGroupThreadsCount(groupId, userId, false);
252     }
253 
254     public int getGroupThreadsCount(
255             long groupId, long userId, boolean subscribed)
256         throws SystemException {
257 
258         return getGroupThreadsCount(groupId, userId, subscribed, true);
259     }
260 
261     public int getGroupThreadsCount(
262             long groupId, long userId, boolean subscribed,
263             boolean includeAnonymous)
264         throws SystemException {
265 
266         if (userId <= 0) {
267             return mbThreadPersistence.countByGroupId(groupId);
268         }
269         else {
270             if (subscribed) {
271                 return mbThreadFinder.countByS_G_U(groupId, userId);
272             }
273             else {
274                 if (includeAnonymous) {
275                     return mbMessageFinder.countByG_U(groupId, userId);
276                 }
277                 else {
278                     return mbMessageFinder.countByG_U_A(groupId, userId, false);
279                 }
280             }
281         }
282     }
283 
284     public MBThread getThread(long threadId)
285         throws PortalException, SystemException {
286 
287         return mbThreadPersistence.findByPrimaryKey(threadId);
288     }
289 
290     public List<MBThread> getThreads(long categoryId, int start, int end)
291         throws SystemException {
292 
293         return mbThreadPersistence.findByCategoryId(categoryId, start, end);
294     }
295 
296     public int getThreadsCount(long categoryId) throws SystemException {
297         return mbThreadPersistence.countByCategoryId(categoryId);
298     }
299 
300     /**
301      * @deprecated
302      */
303     public boolean hasReadThread(long userId, long threadId)
304         throws PortalException, SystemException {
305 
306         MBThread thread = mbThreadLocalService.getThread(threadId);
307 
308         return mbMessageFlagLocalService.hasReadFlag(userId, thread);
309     }
310 
311     public MBThread moveThread(long categoryId, long threadId)
312         throws PortalException, SystemException {
313 
314         MBThread thread = mbThreadPersistence.findByPrimaryKey(
315             threadId);
316 
317         long oldCategoryId = thread.getCategoryId();
318 
319         MBCategory oldCategory = mbCategoryPersistence.findByPrimaryKey(
320             oldCategoryId);
321 
322         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
323             categoryId);
324 
325         // Messages
326 
327         List<MBMessage> messages = mbMessagePersistence.findByC_T(
328             oldCategoryId, thread.getThreadId());
329 
330         for (MBMessage message : messages) {
331             message.setCategoryId(category.getCategoryId());
332 
333             mbMessagePersistence.update(message, false);
334 
335             // Indexer
336 
337             try {
338                 if (!category.isDiscussion()) {
339                     Indexer.updateMessage(
340                         message.getCompanyId(), message.getGroupId(),
341                         message.getUserId(), message.getUserName(),
342                         category.getCategoryId(), message.getThreadId(),
343                         message.getMessageId(), message.getSubject(),
344                         message.getBody(), message.getModifiedDate(),
345                         message.getTagsEntries());
346                 }
347             }
348             catch (SearchException se) {
349                 _log.error("Indexing " + message.getMessageId(), se);
350             }
351         }
352 
353         // Thread
354 
355         thread.setCategoryId(category.getCategoryId());
356 
357         mbThreadPersistence.update(thread, false);
358 
359         // Category
360 
361         oldCategory.setThreadCount(oldCategory.getThreadCount() - 1);
362         oldCategory.setMessageCount(
363             oldCategory.getMessageCount() - messages.size());
364 
365         mbCategoryPersistence.update(oldCategory, false);
366 
367         category.setThreadCount(category.getThreadCount() + 1);
368         category.setMessageCount(category.getMessageCount() + messages.size());
369 
370         mbCategoryPersistence.update(category, false);
371 
372         return thread;
373     }
374 
375     public MBThread splitThread(
376             long messageId, PortletPreferences prefs, ThemeDisplay themeDisplay)
377         throws PortalException, SystemException {
378 
379         MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
380 
381         if (message.isRoot()) {
382             throw new SplitThreadException();
383         }
384 
385         MBCategory category = message.getCategory();
386         long oldThreadId = message.getThreadId();
387         String oldAttachmentsDir = message.getAttachmentsDir();
388 
389         // Message flags
390 
391         mbMessageFlagLocalService.deleteThreadFlags(oldThreadId);
392 
393         // Create new thread
394 
395         MBThread thread = addThread(message.getCategoryId(), message);
396 
397         // Update message
398 
399         message.setThreadId(thread.getThreadId());
400         message.setParentMessageId(0);
401         message.setAttachmentsDir(null);
402 
403         mbMessagePersistence.update(message, false);
404 
405         // Attachments
406 
407         moveAttachmentsFromOldThread(message, oldAttachmentsDir);
408 
409         // Indexer
410 
411         try {
412             if (!category.isDiscussion()) {
413                 Indexer.updateMessage(
414                     message.getCompanyId(), message.getGroupId(),
415                     message.getUserId(), message.getUserName(),
416                     category.getCategoryId(), message.getThreadId(),
417                     message.getMessageId(), message.getSubject(),
418                     message.getBody(), message.getModifiedDate(),
419                     message.getTagsEntries());
420             }
421         }
422         catch (SearchException se) {
423             _log.error("Indexing " + message.getMessageId(), se);
424         }
425 
426         // Update children
427 
428         int messagesMoved = 1;
429 
430         messagesMoved += moveChildrenMessages(
431             message, category, oldThreadId);
432 
433         // Update new thread
434 
435         thread.setMessageCount(messagesMoved);
436 
437         mbThreadPersistence.update(thread, false);
438 
439         // Update old thread
440 
441         MBThread oldThread = mbThreadPersistence.findByPrimaryKey(oldThreadId);
442 
443         oldThread.setMessageCount(oldThread.getMessageCount() - messagesMoved);
444 
445         mbThreadPersistence.update(oldThread, false);
446 
447         // Category
448 
449         category.setThreadCount(category.getThreadCount() + 1);
450 
451         mbCategoryPersistence.update(category, false);
452 
453         return thread;
454     }
455 
456     public MBThread updateThread(long threadId, int viewCount)
457         throws PortalException, SystemException {
458 
459         MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
460 
461         thread.setViewCount(viewCount);
462 
463         mbThreadPersistence.update(thread, false);
464 
465         return thread;
466     }
467 
468     protected MBThread addThread(long categoryId, MBMessage message)
469         throws SystemException {
470 
471         long threadId = counterLocalService.increment();
472 
473         MBThread thread = mbThreadPersistence.create(threadId);
474 
475         thread.setGroupId(message.getGroupId());
476         thread.setCategoryId(categoryId);
477         thread.setRootMessageId(message.getMessageId());
478 
479         thread.setMessageCount(thread.getMessageCount() + 1);
480 
481         if (message.isAnonymous()) {
482             thread.setLastPostByUserId(0);
483         }
484         else {
485             thread.setLastPostByUserId(message.getUserId());
486         }
487 
488         thread.setLastPostDate(message.getCreateDate());
489 
490         if (message.getPriority() != MBThreadImpl.PRIORITY_NOT_GIVEN) {
491             thread.setPriority(message.getPriority());
492         }
493 
494         mbThreadPersistence.update(thread, false);
495 
496         return thread;
497     }
498 
499     protected void moveAttachmentsFromOldThread(
500             MBMessage message, String oldAttachmentsDir)
501         throws PortalException, SystemException {
502 
503         if (!message.getAttachments()) {
504             return;
505         }
506 
507         long companyId = message.getCompanyId();
508         String portletId = CompanyConstants.SYSTEM_STRING;
509         long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
510         long repositoryId = CompanyConstants.SYSTEM;
511         String newAttachmentsDir = message.getAttachmentsDir();
512 
513         try {
514             try {
515                 dlService.addDirectory(
516                     companyId, repositoryId, newAttachmentsDir);
517             }
518             catch (DuplicateDirectoryException dde) {
519             }
520 
521             String[] fileNames = dlService.getFileNames(
522                 companyId, repositoryId, oldAttachmentsDir);
523 
524             for (String fileName : fileNames) {
525                 String name = StringUtil.extractLast(
526                     fileName, StringPool.SLASH);
527                 byte[] fileBytes = dlService.getFile(
528                     companyId, repositoryId, fileName);
529 
530                 dlService.addFile(
531                     companyId, portletId, groupId, repositoryId,
532                     newAttachmentsDir + "/" + name, StringPool.BLANK,
533                     message.getModifiedDate(), new String[0], fileBytes);
534 
535                 dlService.deleteFile(
536                     companyId, portletId, repositoryId, fileName);
537             }
538 
539             try {
540                 dlService.deleteDirectory(
541                     companyId, portletId, repositoryId, oldAttachmentsDir);
542             }
543             catch (NoSuchDirectoryException nsde) {
544             }
545         }
546         catch (RemoteException re) {
547             throw new SystemException(re);
548         }
549     }
550 
551     protected int moveChildrenMessages(
552             MBMessage parentMessage, MBCategory category, long oldThreadId)
553         throws SystemException, PortalException {
554 
555         int messagesMoved = 0;
556 
557         List<MBMessage> messages = mbMessagePersistence.findByT_P(
558             oldThreadId, parentMessage.getMessageId());
559 
560         for (MBMessage message : messages) {
561             String oldAttachmentsDir = message.getAttachmentsDir();
562 
563             message.setCategoryId(parentMessage.getCategoryId());
564             message.setThreadId(parentMessage.getThreadId());
565             message.setAttachmentsDir(null);
566 
567             mbMessagePersistence.update(message, false);
568 
569             moveAttachmentsFromOldThread(message, oldAttachmentsDir);
570 
571             try {
572                 if (!category.isDiscussion()) {
573                     Indexer.updateMessage(
574                         message.getCompanyId(), message.getGroupId(),
575                         message.getUserId(), message.getUserName(),
576                         category.getCategoryId(), message.getThreadId(),
577                         message.getMessageId(), message.getSubject(),
578                         message.getBody(), message.getModifiedDate(),
579                         message.getTagsEntries());
580                 }
581             }
582             catch (SearchException se) {
583                 _log.error("Indexing " + message.getMessageId(), se);
584             }
585 
586             messagesMoved++;
587 
588             messagesMoved += moveChildrenMessages(
589                 message, category, oldThreadId);
590         }
591 
592         return messagesMoved;
593     }
594 
595     private static Log _log =
596         LogFactoryUtil.getLog(MBThreadLocalServiceImpl.class);
597 
598 }