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.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.search.BooleanClauseOccur;
30  import com.liferay.portal.kernel.search.BooleanQuery;
31  import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
32  import com.liferay.portal.kernel.search.Field;
33  import com.liferay.portal.kernel.search.Hits;
34  import com.liferay.portal.kernel.search.SearchEngineUtil;
35  import com.liferay.portal.kernel.search.SearchException;
36  import com.liferay.portal.kernel.search.TermQuery;
37  import com.liferay.portal.kernel.search.TermQueryFactoryUtil;
38  import com.liferay.portal.kernel.util.GetterUtil;
39  import com.liferay.portal.kernel.util.Validator;
40  import com.liferay.portal.model.CompanyConstants;
41  import com.liferay.portal.model.ResourceConstants;
42  import com.liferay.portal.model.User;
43  import com.liferay.portal.service.ServiceContext;
44  import com.liferay.portlet.messageboards.CategoryNameException;
45  import com.liferay.portlet.messageboards.NoSuchMailingListException;
46  import com.liferay.portlet.messageboards.model.MBCategory;
47  import com.liferay.portlet.messageboards.model.MBMailingList;
48  import com.liferay.portlet.messageboards.model.MBMessage;
49  import com.liferay.portlet.messageboards.model.MBThread;
50  import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
51  import com.liferay.portlet.messageboards.service.base.MBCategoryLocalServiceBaseImpl;
52  import com.liferay.portlet.messageboards.util.Indexer;
53  
54  import java.util.ArrayList;
55  import java.util.Date;
56  import java.util.List;
57  
58  /**
59   * <a href="MBCategoryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
60   *
61   * @author Brian Wing Shun Chan
62   *
63   */
64  public class MBCategoryLocalServiceImpl extends MBCategoryLocalServiceBaseImpl {
65  
66      public MBCategory addCategory(
67              long userId, long parentCategoryId, String name, String description,
68              String emailAddress, String inProtocol, String inServerName,
69              int inServerPort, boolean inUseSSL, String inUserName,
70              String inPassword, int inReadInterval, String outEmailAddress,
71              boolean outCustom, String outServerName, int outServerPort,
72              boolean outUseSSL, String outUserName, String outPassword,
73              boolean mailingListActive, ServiceContext serviceContext)
74          throws PortalException, SystemException {
75  
76          return addCategory(
77              null, userId, parentCategoryId, name, description, emailAddress,
78              inProtocol, inServerName, inServerPort, inUseSSL, inUserName,
79              inPassword, inReadInterval, outEmailAddress, outCustom,
80              outServerName, outServerPort, outUseSSL, outUserName, outPassword,
81              mailingListActive, serviceContext);
82      }
83  
84      public MBCategory addCategory(
85              String uuid, long userId, long parentCategoryId,
86              String name, String description, String emailAddress,
87              String inProtocol, String inServerName, int inServerPort,
88              boolean inUseSSL, String inUserName, String inPassword,
89              int inReadInterval, String outEmailAddress, boolean outCustom,
90              String outServerName, int outServerPort, boolean outUseSSL,
91              String outUserName, String outPassword, boolean mailingListActive,
92              ServiceContext serviceContext)
93          throws PortalException, SystemException {
94  
95          // Category
96  
97          User user = userPersistence.findByPrimaryKey(userId);
98          long groupId = serviceContext.getScopeGroupId();
99          parentCategoryId = getParentCategoryId(groupId, parentCategoryId);
100         Date now = new Date();
101 
102         validate(name);
103 
104         long categoryId = counterLocalService.increment();
105 
106         MBCategory category = mbCategoryPersistence.create(categoryId);
107 
108         category.setUuid(uuid);
109         category.setGroupId(groupId);
110         category.setCompanyId(user.getCompanyId());
111         category.setUserId(user.getUserId());
112         category.setUserName(user.getFullName());
113         category.setCreateDate(now);
114         category.setModifiedDate(now);
115         category.setParentCategoryId(parentCategoryId);
116         category.setName(name);
117         category.setDescription(description);
118 
119         mbCategoryPersistence.update(category, false);
120 
121         // Resources
122 
123         if (serviceContext.getAddCommunityPermissions() ||
124             serviceContext.getAddGuestPermissions()) {
125 
126             addCategoryResources(
127                 category, serviceContext.getAddCommunityPermissions(),
128                 serviceContext.getAddGuestPermissions());
129         }
130         else {
131             addCategoryResources(
132                 category, serviceContext.getCommunityPermissions(),
133                 serviceContext.getGuestPermissions());
134         }
135 
136         // Mailing list
137 
138         mbMailingListLocalService.addMailingList(
139             null, userId, category.getCategoryId(), emailAddress, inProtocol,
140             inServerName, inServerPort, inUseSSL, inUserName, inPassword,
141             inReadInterval, outEmailAddress, outCustom, outServerName,
142             outServerPort, outUseSSL, outUserName, outPassword,
143             mailingListActive);
144 
145         return category;
146     }
147 
148     public void addCategoryResources(
149             long categoryId, boolean addCommunityPermissions,
150             boolean addGuestPermissions)
151         throws PortalException, SystemException {
152 
153         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
154             categoryId);
155 
156         addCategoryResources(
157             category, addCommunityPermissions, addGuestPermissions);
158     }
159 
160     public void addCategoryResources(
161             MBCategory category, boolean addCommunityPermissions,
162             boolean addGuestPermissions)
163         throws PortalException, SystemException {
164 
165         resourceLocalService.addResources(
166             category.getCompanyId(), category.getGroupId(),
167             category.getUserId(), MBCategory.class.getName(),
168             category.getCategoryId(), false, addCommunityPermissions,
169             addGuestPermissions);
170     }
171 
172     public void addCategoryResources(
173             long categoryId, String[] communityPermissions,
174             String[] guestPermissions)
175         throws PortalException, SystemException {
176 
177         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
178             categoryId);
179 
180         addCategoryResources(category, communityPermissions, guestPermissions);
181     }
182 
183     public void addCategoryResources(
184             MBCategory category, String[] communityPermissions,
185             String[] guestPermissions)
186         throws PortalException, SystemException {
187 
188         resourceLocalService.addModelResources(
189             category.getCompanyId(), category.getGroupId(),
190             category.getUserId(), MBCategory.class.getName(),
191             category.getCategoryId(), communityPermissions, guestPermissions);
192     }
193 
194     public void deleteCategories(long groupId)
195         throws PortalException, SystemException {
196 
197         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
198             groupId, MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID);
199 
200         for (MBCategory category : categories) {
201             deleteCategory(category);
202         }
203     }
204 
205     public void deleteCategory(long categoryId)
206         throws PortalException, SystemException {
207 
208         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
209             categoryId);
210 
211         deleteCategory(category);
212     }
213 
214     public void deleteCategory(MBCategory category)
215         throws PortalException, SystemException {
216 
217         // Categories
218 
219         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
220             category.getGroupId(), category.getCategoryId());
221 
222         for (MBCategory curCategory : categories) {
223             deleteCategory(curCategory);
224         }
225 
226         // Indexer
227 
228         try {
229             Indexer.deleteMessages(
230                 category.getCompanyId(), category.getCategoryId());
231         }
232         catch (SearchException se) {
233             _log.error("Deleting index " + category.getCategoryId(), se);
234         }
235 
236         // Threads
237 
238         mbThreadLocalService.deleteThreads(category.getCategoryId());
239 
240         // Mailing list
241 
242         try {
243             mbMailingListLocalService.deleteCategoryMailingList(
244                 category.getCategoryId());
245         }
246         catch (NoSuchMailingListException nsmle) {
247         }
248 
249         // Resources
250 
251         resourceLocalService.deleteResource(
252             category.getCompanyId(), MBCategory.class.getName(),
253             ResourceConstants.SCOPE_INDIVIDUAL, category.getCategoryId());
254 
255         // Category
256 
257         mbCategoryPersistence.remove(category);
258     }
259 
260     public List<MBCategory> getCategories(long groupId, long parentCategoryId)
261         throws SystemException {
262 
263         return mbCategoryPersistence.findByG_P(groupId, parentCategoryId);
264     }
265 
266     public List<MBCategory> getCategories(
267             long groupId, long parentCategoryId, int start, int end)
268         throws SystemException {
269 
270         return mbCategoryPersistence.findByG_P(
271             groupId, parentCategoryId, start, end);
272     }
273 
274     public int getCategoriesCount(long groupId) throws SystemException {
275         return mbCategoryPersistence.countByGroupId(groupId);
276     }
277 
278     public int getCategoriesCount(long groupId, long parentCategoryId)
279         throws SystemException {
280 
281         return mbCategoryPersistence.countByG_P(groupId, parentCategoryId);
282     }
283 
284     public MBCategory getCategory(long categoryId)
285         throws PortalException, SystemException {
286 
287         return mbCategoryPersistence.findByPrimaryKey(categoryId);
288     }
289 
290     public void getSubcategoryIds(
291             List<Long> categoryIds, long groupId, long categoryId)
292         throws SystemException {
293 
294         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
295             groupId, categoryId);
296 
297         for (MBCategory category : categories) {
298             categoryIds.add(category.getCategoryId());
299 
300             getSubcategoryIds(
301                 categoryIds, category.getGroupId(), category.getCategoryId());
302         }
303     }
304 
305     public List<MBCategory> getSubscribedCategories(
306             long groupId, long userId, int start, int end)
307         throws SystemException {
308 
309         return mbCategoryFinder.findByS_G_U(groupId, userId, start, end);
310     }
311 
312     public int getSubscribedCategoriesCount(long groupId, long userId)
313         throws SystemException {
314 
315         return mbCategoryFinder.countByS_G_U(groupId, userId);
316     }
317 
318     public MBCategory getSystemCategory() throws SystemException {
319         long categoryId = CompanyConstants.SYSTEM;
320 
321         MBCategory category = mbCategoryPersistence.fetchByPrimaryKey(
322             categoryId);
323 
324         if (category == null) {
325             category = mbCategoryPersistence.create(categoryId);
326 
327             category.setCompanyId(CompanyConstants.SYSTEM);
328             category.setUserId(CompanyConstants.SYSTEM);
329 
330             mbCategoryPersistence.update(category, false);
331         }
332 
333         return category;
334     }
335 
336     public void reIndex(String[] ids) throws SystemException {
337         if (SearchEngineUtil.isIndexReadOnly()) {
338             return;
339         }
340 
341         long companyId = GetterUtil.getLong(ids[0]);
342 
343         try {
344             List<MBCategory> categories = mbCategoryPersistence.findByCompanyId(
345                 companyId);
346 
347             for (MBCategory category : categories) {
348                 long categoryId = category.getCategoryId();
349 
350                 List<MBMessage> messages =
351                     mbMessagePersistence.findByCategoryId(categoryId);
352 
353                 for (MBMessage message : messages) {
354                     long groupId = category.getGroupId();
355                     long userId = message.getUserId();
356                     String userName = message.getUserName();
357                     long threadId = message.getThreadId();
358                     long messageId = message.getMessageId();
359                     String title = message.getSubject();
360                     String content = message.getBody();
361                     boolean anonymous = message.isAnonymous();
362                     Date modifiedDate = message.getModifiedDate();
363 
364                     String[] tagsEntries = tagsEntryLocalService.getEntryNames(
365                         MBMessage.class.getName(), messageId);
366 
367                     try {
368                         Indexer.updateMessage(
369                             companyId, groupId, userId, userName, categoryId,
370                             threadId, messageId, title, content, anonymous,
371                             modifiedDate, tagsEntries,
372                             message.getExpandoBridge());
373                     }
374                     catch (SearchException se) {
375                         _log.error("Reindexing " + messageId, se);
376                     }
377                 }
378             }
379         }
380         catch (SystemException se) {
381             throw se;
382         }
383         catch (Exception e) {
384             throw new SystemException(e);
385         }
386     }
387 
388     public Hits search(
389             long companyId, long groupId, long[] categoryIds, long threadId,
390             String keywords, int start, int end)
391         throws SystemException {
392 
393         try {
394             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
395 
396             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
397 
398             if (groupId > 0) {
399                 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
400             }
401 
402             if ((categoryIds != null) && (categoryIds.length > 0)) {
403                 BooleanQuery categoryIdsQuery =
404                     BooleanQueryFactoryUtil.create();
405 
406                 for (long categoryId : categoryIds) {
407                     TermQuery termQuery = TermQueryFactoryUtil.create(
408                         "categoryId", categoryId);
409 
410                     categoryIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
411                 }
412 
413                 contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
414             }
415 
416             if (threadId > 0) {
417                 contextQuery.addTerm("threadId", threadId);
418             }
419 
420             BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
421 
422             if (Validator.isNotNull(keywords)) {
423                 searchQuery.addTerm(Field.USER_NAME, keywords);
424                 searchQuery.addTerm(Field.TITLE, keywords);
425                 searchQuery.addTerm(Field.CONTENT, keywords);
426                 searchQuery.addTerm(Field.TAGS_ENTRIES, keywords);
427             }
428 
429             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
430 
431             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
432 
433             if (searchQuery.clauses().size() > 0) {
434                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
435             }
436 
437             return SearchEngineUtil.search(companyId, fullQuery, start, end);
438         }
439         catch (Exception e) {
440             throw new SystemException(e);
441         }
442     }
443 
444     public MBCategory updateCategory(
445             long categoryId, long parentCategoryId, String name,
446             String description, String emailAddress, String inProtocol,
447             String inServerName, int inServerPort, boolean inUseSSL,
448             String inUserName, String inPassword, int inReadInterval,
449             String outEmailAddress, boolean outCustom, String outServerName,
450             int outServerPort, boolean outUseSSL, String outUserName,
451             String outPassword, boolean mailingListActive,
452             boolean mergeWithParentCategory)
453         throws PortalException, SystemException {
454 
455         // Category
456 
457         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
458             categoryId);
459 
460         parentCategoryId = getParentCategoryId(category, parentCategoryId);
461 
462         validate(name);
463 
464         category.setModifiedDate(new Date());
465         category.setParentCategoryId(parentCategoryId);
466         category.setName(name);
467         category.setDescription(description);
468 
469         mbCategoryPersistence.update(category, false);
470 
471         // Merge categories
472 
473         if (mergeWithParentCategory &&
474             (categoryId != parentCategoryId) &&
475             (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID)) {
476 
477             mergeCategories(category, parentCategoryId);
478         }
479 
480         // Mailing list
481 
482         MBMailingList mailingList = mbMailingListPersistence.fetchByCategoryId(
483             category.getCategoryId());
484 
485         if (mailingList != null) {
486             mbMailingListLocalService.updateMailingList(
487                 mailingList.getMailingListId(), emailAddress, inProtocol,
488                 inServerName, inServerPort, inUseSSL, inUserName, inPassword,
489                 inReadInterval, outEmailAddress, outCustom, outServerName,
490                 outServerPort, outUseSSL, outUserName, outPassword,
491                 mailingListActive);
492         }
493         else {
494             mbMailingListLocalService.addMailingList(
495                 null, category.getUserId(), category.getCategoryId(),
496                 emailAddress, inProtocol, inServerName, inServerPort, inUseSSL,
497                 inUserName, inPassword, inReadInterval, outEmailAddress,
498                 outCustom, outServerName, outServerPort, outUseSSL, outUserName,
499                 outPassword, mailingListActive);
500         }
501 
502         return category;
503     }
504 
505     protected long getParentCategoryId(long groupId, long parentCategoryId)
506         throws SystemException {
507 
508         if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
509             MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
510                 parentCategoryId);
511 
512             if ((parentCategory == null) ||
513                 (groupId != parentCategory.getGroupId())) {
514 
515                 parentCategoryId = MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID;
516             }
517         }
518 
519         return parentCategoryId;
520     }
521 
522     protected long getParentCategoryId(
523             MBCategory category, long parentCategoryId)
524         throws SystemException {
525 
526         if (parentCategoryId == MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
527             return parentCategoryId;
528         }
529 
530         if (category.getCategoryId() == parentCategoryId) {
531             return category.getParentCategoryId();
532         }
533         else {
534             MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
535                 parentCategoryId);
536 
537             if ((parentCategory == null) ||
538                 (category.getGroupId() != parentCategory.getGroupId())) {
539 
540                 return category.getParentCategoryId();
541             }
542 
543             List<Long> subcategoryIds = new ArrayList<Long>();
544 
545             getSubcategoryIds(
546                 subcategoryIds, category.getGroupId(),
547                 category.getCategoryId());
548 
549             if (subcategoryIds.contains(parentCategoryId)) {
550                 return category.getParentCategoryId();
551             }
552 
553             return parentCategoryId;
554         }
555     }
556 
557     protected void mergeCategories(MBCategory fromCategory, long toCategoryId)
558         throws PortalException, SystemException {
559 
560         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
561             fromCategory.getGroupId(), fromCategory.getCategoryId());
562 
563         for (MBCategory category : categories) {
564             mergeCategories(category, toCategoryId);
565         }
566 
567         List<MBThread> threads = mbThreadPersistence.findByCategoryId(
568             fromCategory.getCategoryId());
569 
570         for (MBThread thread : threads) {
571 
572             // Thread
573 
574             thread.setCategoryId(toCategoryId);
575 
576             mbThreadPersistence.update(thread, false);
577 
578             List<MBMessage> messages = mbMessagePersistence.findByThreadId(
579                 thread.getThreadId());
580 
581             for (MBMessage message : messages) {
582 
583                 // Message
584 
585                 message.setCategoryId(toCategoryId);
586 
587                 mbMessagePersistence.update(message, false);
588 
589                 // Indexer
590 
591                 try {
592                     if (!fromCategory.isDiscussion()) {
593                         String[] tagsEntries =
594                             tagsEntryLocalService.getEntryNames(
595                                 MBMessage.class.getName(),
596                                 message.getMessageId());
597 
598                         Indexer.updateMessage(
599                             message.getCompanyId(), fromCategory.getGroupId(),
600                             message.getUserId(), message.getUserName(),
601                             toCategoryId, message.getThreadId(),
602                             message.getMessageId(), message.getSubject(),
603                             message.getBody(), message.isAnonymous(),
604                             message.getModifiedDate(), tagsEntries,
605                             message.getExpandoBridge());
606                     }
607                 }
608                 catch (SearchException se) {
609                     _log.error("Indexing " + message.getMessageId(), se);
610                 }
611             }
612         }
613 
614         deleteCategory(fromCategory);
615     }
616 
617     public void subscribeCategory(long userId, long categoryId)
618         throws PortalException, SystemException {
619 
620         subscriptionLocalService.addSubscription(
621             userId, MBCategory.class.getName(), categoryId);
622     }
623 
624     public void unsubscribeCategory(long userId, long categoryId)
625         throws PortalException, SystemException {
626 
627         subscriptionLocalService.deleteSubscription(
628             userId, MBCategory.class.getName(), categoryId);
629     }
630 
631     protected void validate(String name) throws PortalException {
632         if (Validator.isNull(name)) {
633             throw new CategoryNameException();
634         }
635     }
636 
637     private static Log _log =
638         LogFactoryUtil.getLog(MBCategoryLocalServiceImpl.class);
639 
640 }