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