1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights 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.Group;
42  import com.liferay.portal.model.ResourceConstants;
43  import com.liferay.portal.model.User;
44  import com.liferay.portal.service.ServiceContext;
45  import com.liferay.portlet.messageboards.CategoryNameException;
46  import com.liferay.portlet.messageboards.NoSuchMailingListException;
47  import com.liferay.portlet.messageboards.model.MBCategory;
48  import com.liferay.portlet.messageboards.model.MBMailingList;
49  import com.liferay.portlet.messageboards.model.MBMessage;
50  import com.liferay.portlet.messageboards.model.MBThread;
51  import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
52  import com.liferay.portlet.messageboards.service.base.MBCategoryLocalServiceBaseImpl;
53  import com.liferay.portlet.messageboards.util.Indexer;
54  
55  import java.util.ArrayList;
56  import java.util.Date;
57  import java.util.List;
58  
59  /**
60   * <a href="MBCategoryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
61   *
62   * @author Brian Wing Shun Chan
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             long categoryId, String[] communityPermissions,
162             String[] guestPermissions)
163         throws PortalException, SystemException {
164 
165         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
166             categoryId);
167 
168         addCategoryResources(category, communityPermissions, guestPermissions);
169     }
170 
171     public void addCategoryResources(
172             MBCategory category, boolean addCommunityPermissions,
173             boolean addGuestPermissions)
174         throws PortalException, SystemException {
175 
176         resourceLocalService.addResources(
177             category.getCompanyId(), category.getGroupId(),
178             category.getUserId(), MBCategory.class.getName(),
179             category.getCategoryId(), false, addCommunityPermissions,
180             addGuestPermissions);
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) throws SystemException {
261         return mbCategoryPersistence.findByGroupId(groupId);
262     }
263 
264     public List<MBCategory> getCategories(long groupId, long parentCategoryId)
265         throws SystemException {
266 
267         return mbCategoryPersistence.findByG_P(groupId, parentCategoryId);
268     }
269 
270     public List<MBCategory> getCategories(
271             long groupId, long parentCategoryId, int start, int end)
272         throws SystemException {
273 
274         return mbCategoryPersistence.findByG_P(
275             groupId, parentCategoryId, start, end);
276     }
277 
278     public int getCategoriesCount(long groupId) throws SystemException {
279         return mbCategoryPersistence.countByGroupId(groupId);
280     }
281 
282     public int getCategoriesCount(long groupId, long parentCategoryId)
283         throws SystemException {
284 
285         return mbCategoryPersistence.countByG_P(groupId, parentCategoryId);
286     }
287 
288     public MBCategory getCategory(long categoryId)
289         throws PortalException, SystemException {
290 
291         return mbCategoryPersistence.findByPrimaryKey(categoryId);
292     }
293 
294     public void getSubcategoryIds(
295             List<Long> categoryIds, long groupId, long categoryId)
296         throws SystemException {
297 
298         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
299             groupId, categoryId);
300 
301         for (MBCategory category : categories) {
302             categoryIds.add(category.getCategoryId());
303 
304             getSubcategoryIds(
305                 categoryIds, category.getGroupId(), category.getCategoryId());
306         }
307     }
308 
309     public List<MBCategory> getSubscribedCategories(
310             long groupId, long userId, int start, int end)
311         throws SystemException {
312 
313         return mbCategoryFinder.findByS_G_U(groupId, userId, start, end);
314     }
315 
316     public int getSubscribedCategoriesCount(long groupId, long userId)
317         throws SystemException {
318 
319         return mbCategoryFinder.countByS_G_U(groupId, userId);
320     }
321 
322     public MBCategory getSystemCategory() throws SystemException {
323         long categoryId = CompanyConstants.SYSTEM;
324 
325         MBCategory category = mbCategoryPersistence.fetchByPrimaryKey(
326             categoryId);
327 
328         if (category == null) {
329             category = mbCategoryPersistence.create(categoryId);
330 
331             category.setCompanyId(CompanyConstants.SYSTEM);
332             category.setUserId(CompanyConstants.SYSTEM);
333 
334             mbCategoryPersistence.update(category, false);
335         }
336 
337         return category;
338     }
339 
340     public void reIndex(String[] ids) throws SystemException {
341         if (SearchEngineUtil.isIndexReadOnly()) {
342             return;
343         }
344 
345         long companyId = GetterUtil.getLong(ids[0]);
346 
347         try {
348             reIndexCategories(companyId);
349         }
350         catch (SystemException se) {
351             throw se;
352         }
353         catch (Exception e) {
354             throw new SystemException(e);
355         }
356     }
357 
358     public Hits search(
359             long companyId, long groupId, long userId, long[] categoryIds,
360             long threadId, String keywords, int start, int end)
361         throws SystemException {
362 
363         try {
364             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
365 
366             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
367 
368             if (groupId > 0) {
369                 Group group = groupLocalService.getGroup(groupId);
370 
371                 if (group.isLayout()) {
372                     contextQuery.addRequiredTerm(Field.SCOPE_GROUP_ID, groupId);
373 
374                     groupId = group.getParentGroupId();
375                 }
376 
377                 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
378             }
379 
380             if ((categoryIds != null) && (categoryIds.length > 0)) {
381                 BooleanQuery categoryIdsQuery =
382                     BooleanQueryFactoryUtil.create();
383 
384                 for (long categoryId : categoryIds) {
385                     TermQuery termQuery = TermQueryFactoryUtil.create(
386                         "categoryId", categoryId);
387 
388                     categoryIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
389                 }
390 
391                 contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
392             }
393 
394             if (threadId > 0) {
395                 contextQuery.addTerm("threadId", threadId);
396             }
397 
398             BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
399 
400             if (Validator.isNotNull(keywords)) {
401                 searchQuery.addTerm(Field.USER_NAME, keywords);
402                 searchQuery.addTerm(Field.TITLE, keywords);
403                 searchQuery.addTerm(Field.CONTENT, keywords);
404                 searchQuery.addTerm(Field.TAGS_ENTRIES, keywords, true);
405             }
406 
407             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
408 
409             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
410 
411             if (searchQuery.clauses().size() > 0) {
412                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
413             }
414 
415             return SearchEngineUtil.search(
416                 companyId, groupId, userId, MBMessage.class.getName(),
417                 fullQuery, start, end);
418         }
419         catch (Exception e) {
420             throw new SystemException(e);
421         }
422     }
423 
424     public void subscribeCategory(long userId, long categoryId)
425         throws PortalException, SystemException {
426 
427         subscriptionLocalService.addSubscription(
428             userId, MBCategory.class.getName(), categoryId);
429     }
430 
431     public void unsubscribeCategory(long userId, long categoryId)
432         throws PortalException, SystemException {
433 
434         subscriptionLocalService.deleteSubscription(
435             userId, MBCategory.class.getName(), categoryId);
436     }
437 
438     public MBCategory updateCategory(
439             long categoryId, long parentCategoryId, String name,
440             String description, String emailAddress, String inProtocol,
441             String inServerName, int inServerPort, boolean inUseSSL,
442             String inUserName, String inPassword, int inReadInterval,
443             String outEmailAddress, boolean outCustom, String outServerName,
444             int outServerPort, boolean outUseSSL, String outUserName,
445             String outPassword, boolean mailingListActive,
446             boolean mergeWithParentCategory)
447         throws PortalException, SystemException {
448 
449         // Category
450 
451         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
452             categoryId);
453 
454         parentCategoryId = getParentCategoryId(category, parentCategoryId);
455 
456         validate(name);
457 
458         category.setModifiedDate(new Date());
459         category.setParentCategoryId(parentCategoryId);
460         category.setName(name);
461         category.setDescription(description);
462 
463         mbCategoryPersistence.update(category, false);
464 
465         // Merge categories
466 
467         if (mergeWithParentCategory &&
468             (categoryId != parentCategoryId) &&
469             (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID)) {
470 
471             mergeCategories(category, parentCategoryId);
472         }
473 
474         // Mailing list
475 
476         MBMailingList mailingList = mbMailingListPersistence.fetchByCategoryId(
477             category.getCategoryId());
478 
479         if (mailingList != null) {
480             mbMailingListLocalService.updateMailingList(
481                 mailingList.getMailingListId(), emailAddress, inProtocol,
482                 inServerName, inServerPort, inUseSSL, inUserName, inPassword,
483                 inReadInterval, outEmailAddress, outCustom, outServerName,
484                 outServerPort, outUseSSL, outUserName, outPassword,
485                 mailingListActive);
486         }
487         else {
488             mbMailingListLocalService.addMailingList(
489                 null, category.getUserId(), category.getCategoryId(),
490                 emailAddress, inProtocol, inServerName, inServerPort, inUseSSL,
491                 inUserName, inPassword, inReadInterval, outEmailAddress,
492                 outCustom, outServerName, outServerPort, outUseSSL, outUserName,
493                 outPassword, mailingListActive);
494         }
495 
496         return category;
497     }
498 
499     protected long getParentCategoryId(long groupId, long parentCategoryId)
500         throws SystemException {
501 
502         if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
503             MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
504                 parentCategoryId);
505 
506             if ((parentCategory == null) ||
507                 (groupId != parentCategory.getGroupId())) {
508 
509                 parentCategoryId = MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID;
510             }
511         }
512 
513         return parentCategoryId;
514     }
515 
516     protected long getParentCategoryId(
517             MBCategory category, long parentCategoryId)
518         throws SystemException {
519 
520         if (parentCategoryId == MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
521             return parentCategoryId;
522         }
523 
524         if (category.getCategoryId() == parentCategoryId) {
525             return category.getParentCategoryId();
526         }
527         else {
528             MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
529                 parentCategoryId);
530 
531             if ((parentCategory == null) ||
532                 (category.getGroupId() != parentCategory.getGroupId())) {
533 
534                 return category.getParentCategoryId();
535             }
536 
537             List<Long> subcategoryIds = new ArrayList<Long>();
538 
539             getSubcategoryIds(
540                 subcategoryIds, category.getGroupId(),
541                 category.getCategoryId());
542 
543             if (subcategoryIds.contains(parentCategoryId)) {
544                 return category.getParentCategoryId();
545             }
546 
547             return parentCategoryId;
548         }
549     }
550 
551     protected void mergeCategories(MBCategory fromCategory, long toCategoryId)
552         throws PortalException, SystemException {
553 
554         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
555             fromCategory.getGroupId(), fromCategory.getCategoryId());
556 
557         for (MBCategory category : categories) {
558             mergeCategories(category, toCategoryId);
559         }
560 
561         List<MBThread> threads = mbThreadPersistence.findByCategoryId(
562             fromCategory.getCategoryId());
563 
564         for (MBThread thread : threads) {
565 
566             // Thread
567 
568             thread.setCategoryId(toCategoryId);
569 
570             mbThreadPersistence.update(thread, false);
571 
572             List<MBMessage> messages = mbMessagePersistence.findByThreadId(
573                 thread.getThreadId());
574 
575             for (MBMessage message : messages) {
576 
577                 // Message
578 
579                 message.setCategoryId(toCategoryId);
580 
581                 mbMessagePersistence.update(message, false);
582 
583                 // Indexer
584 
585                 mbMessageLocalService.reIndex(message);
586             }
587         }
588 
589         deleteCategory(fromCategory);
590     }
591 
592     protected void reIndexCategories(long companyId) throws SystemException {
593         int categoryCount = mbCategoryPersistence.countByCompanyId(companyId);
594 
595         int categoryPages = categoryCount / Indexer.DEFAULT_INTERVAL;
596 
597         for (int i = 0; i <= categoryPages; i++) {
598             int categoryStart = (i * Indexer.DEFAULT_INTERVAL);
599             int categoryEnd = categoryStart + Indexer.DEFAULT_INTERVAL;
600 
601             reIndexCategories(companyId, categoryStart, categoryEnd);
602         }
603     }
604 
605     protected void reIndexCategories(
606             long companyId, int categoryStart, int categoryEnd)
607         throws SystemException {
608 
609         List<MBCategory> categories = mbCategoryPersistence.findByCompanyId(
610             companyId, categoryStart, categoryEnd);
611 
612         for (MBCategory category : categories) {
613             long categoryId = category.getCategoryId();
614 
615             int messageCount = mbMessagePersistence.countByCategoryId(
616                 categoryId);
617 
618             int messagePages = messageCount / Indexer.DEFAULT_INTERVAL;
619 
620             for (int i = 0; i <= messagePages; i++) {
621                 int messageStart = (i * Indexer.DEFAULT_INTERVAL);
622                 int messageEnd = messageStart + Indexer.DEFAULT_INTERVAL;
623 
624                 reIndexMessages(categoryId, messageStart, messageEnd);
625             }
626         }
627     }
628 
629     protected void reIndexMessages(
630             long categoryId, int messageStart, int messageEnd)
631         throws SystemException {
632 
633         List<MBMessage> messages = mbMessagePersistence.findByCategoryId(
634             categoryId, messageStart, messageEnd);
635 
636         for (MBMessage message : messages) {
637             mbMessageLocalService.reIndex(message);
638         }
639     }
640 
641     protected void validate(String name) throws PortalException {
642         if (Validator.isNull(name)) {
643             throw new CategoryNameException();
644         }
645     }
646 
647     private static Log _log =
648         LogFactoryUtil.getLog(MBCategoryLocalServiceImpl.class);
649 
650 }