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