001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.portlet.messageboards.service.impl;
022:
023: import com.liferay.portal.PortalException;
024: import com.liferay.portal.SystemException;
025: import com.liferay.portal.kernel.search.Hits;
026: import com.liferay.portal.kernel.util.GetterUtil;
027: import com.liferay.portal.kernel.util.Validator;
028: import com.liferay.portal.lucene.LuceneFields;
029: import com.liferay.portal.lucene.LuceneUtil;
030: import com.liferay.portal.model.User;
031: import com.liferay.portal.model.impl.CompanyImpl;
032: import com.liferay.portal.model.impl.ResourceImpl;
033: import com.liferay.portal.util.PortalUtil;
034: import com.liferay.portlet.messageboards.CategoryNameException;
035: import com.liferay.portlet.messageboards.model.MBCategory;
036: import com.liferay.portlet.messageboards.model.MBMessage;
037: import com.liferay.portlet.messageboards.model.MBThread;
038: import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
039: import com.liferay.portlet.messageboards.service.base.MBCategoryLocalServiceBaseImpl;
040: import com.liferay.portlet.messageboards.util.Indexer;
041: import com.liferay.util.lucene.HitsImpl;
042:
043: import java.io.IOException;
044:
045: import java.util.ArrayList;
046: import java.util.Date;
047: import java.util.Iterator;
048: import java.util.List;
049:
050: import org.apache.commons.logging.Log;
051: import org.apache.commons.logging.LogFactory;
052: import org.apache.lucene.document.Document;
053: import org.apache.lucene.index.IndexWriter;
054: import org.apache.lucene.index.Term;
055: import org.apache.lucene.queryParser.ParseException;
056: import org.apache.lucene.search.BooleanClause;
057: import org.apache.lucene.search.BooleanQuery;
058: import org.apache.lucene.search.Searcher;
059: import org.apache.lucene.search.TermQuery;
060:
061: /**
062: * <a href="MBCategoryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
063: *
064: * @author Brian Wing Shun Chan
065: *
066: */
067: public class MBCategoryLocalServiceImpl extends
068: MBCategoryLocalServiceBaseImpl {
069:
070: public MBCategory addCategory(long userId, long plid,
071: long parentCategoryId, String name, String description,
072: boolean addCommunityPermissions, boolean addGuestPermissions)
073: throws PortalException, SystemException {
074:
075: return addCategory(null, userId, plid, parentCategoryId, name,
076: description, Boolean.valueOf(addCommunityPermissions),
077: Boolean.valueOf(addGuestPermissions), null, null);
078: }
079:
080: public MBCategory addCategory(String uuid, long userId, long plid,
081: long parentCategoryId, String name, String description,
082: boolean addCommunityPermissions, boolean addGuestPermissions)
083: throws PortalException, SystemException {
084:
085: return addCategory(uuid, userId, plid, parentCategoryId, name,
086: description, Boolean.valueOf(addCommunityPermissions),
087: Boolean.valueOf(addGuestPermissions), null, null);
088: }
089:
090: public MBCategory addCategory(long userId, long plid,
091: long parentCategoryId, String name, String description,
092: String[] communityPermissions, String[] guestPermissions)
093: throws PortalException, SystemException {
094:
095: return addCategory(null, userId, plid, parentCategoryId, name,
096: description, null, null, communityPermissions,
097: guestPermissions);
098: }
099:
100: public MBCategory addCategory(String uuid, long userId, long plid,
101: long parentCategoryId, String name, String description,
102: Boolean addCommunityPermissions,
103: Boolean addGuestPermissions, String[] communityPermissions,
104: String[] guestPermissions) throws PortalException,
105: SystemException {
106:
107: // Category
108:
109: User user = userPersistence.findByPrimaryKey(userId);
110: long groupId = PortalUtil.getPortletGroupId(plid);
111: parentCategoryId = getParentCategoryId(groupId,
112: parentCategoryId);
113: Date now = new Date();
114:
115: validate(name);
116:
117: long categoryId = counterLocalService.increment();
118:
119: MBCategory category = mbCategoryPersistence.create(categoryId);
120:
121: category.setUuid(uuid);
122: category.setGroupId(groupId);
123: category.setCompanyId(user.getCompanyId());
124: category.setUserId(user.getUserId());
125: category.setUserName(user.getFullName());
126: category.setCreateDate(now);
127: category.setModifiedDate(now);
128: category.setParentCategoryId(parentCategoryId);
129: category.setName(name);
130: category.setDescription(description);
131:
132: mbCategoryPersistence.update(category);
133:
134: // Resources
135:
136: if ((addCommunityPermissions != null)
137: && (addGuestPermissions != null)) {
138:
139: addCategoryResources(category, addCommunityPermissions
140: .booleanValue(), addGuestPermissions.booleanValue());
141: } else {
142: addCategoryResources(category, communityPermissions,
143: guestPermissions);
144: }
145:
146: return category;
147: }
148:
149: public void addCategoryResources(long categoryId,
150: boolean addCommunityPermissions, boolean addGuestPermissions)
151: throws PortalException, SystemException {
152:
153: MBCategory category = mbCategoryPersistence
154: .findByPrimaryKey(categoryId);
155:
156: addCategoryResources(category, addCommunityPermissions,
157: addGuestPermissions);
158: }
159:
160: public void addCategoryResources(MBCategory category,
161: boolean addCommunityPermissions, boolean addGuestPermissions)
162: throws PortalException, SystemException {
163:
164: resourceLocalService.addResources(category.getCompanyId(),
165: category.getGroupId(), category.getUserId(),
166: MBCategory.class.getName(), category.getCategoryId(),
167: false, addCommunityPermissions, addGuestPermissions);
168: }
169:
170: public void addCategoryResources(long categoryId,
171: String[] communityPermissions, String[] guestPermissions)
172: throws PortalException, SystemException {
173:
174: MBCategory category = mbCategoryPersistence
175: .findByPrimaryKey(categoryId);
176:
177: addCategoryResources(category, communityPermissions,
178: guestPermissions);
179: }
180:
181: public void addCategoryResources(MBCategory category,
182: String[] communityPermissions, String[] guestPermissions)
183: throws PortalException, SystemException {
184:
185: resourceLocalService.addModelResources(category.getCompanyId(),
186: category.getGroupId(), category.getUserId(),
187: MBCategory.class.getName(), category.getCategoryId(),
188: communityPermissions, guestPermissions);
189: }
190:
191: public void deleteCategories(long groupId) throws PortalException,
192: SystemException {
193:
194: Iterator itr = mbCategoryPersistence.findByG_P(groupId,
195: MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID).iterator();
196:
197: while (itr.hasNext()) {
198: MBCategory category = (MBCategory) itr.next();
199:
200: deleteCategory(category);
201: }
202: }
203:
204: public void deleteCategory(long categoryId) throws PortalException,
205: SystemException {
206:
207: MBCategory category = mbCategoryPersistence
208: .findByPrimaryKey(categoryId);
209:
210: deleteCategory(category);
211: }
212:
213: public void deleteCategory(MBCategory category)
214: throws PortalException, SystemException {
215:
216: // Categories
217:
218: Iterator itr = mbCategoryPersistence.findByG_P(
219: category.getGroupId(), category.getCategoryId())
220: .iterator();
221:
222: while (itr.hasNext()) {
223: MBCategory curCategory = (MBCategory) itr.next();
224:
225: deleteCategory(curCategory);
226: }
227:
228: // Lucene
229:
230: try {
231: Indexer.deleteMessages(category.getCompanyId(), category
232: .getCategoryId());
233: } catch (IOException ioe) {
234: _log.error("Deleting index " + category.getCategoryId(),
235: ioe);
236: } catch (ParseException pe) {
237: _log
238: .error(
239: "Deleting index "
240: + category.getCategoryId(), pe);
241: }
242:
243: // Threads
244:
245: mbThreadLocalService.deleteThreads(category.getCategoryId());
246:
247: // Resources
248:
249: resourceLocalService
250: .deleteResource(category.getCompanyId(),
251: MBCategory.class.getName(),
252: ResourceImpl.SCOPE_INDIVIDUAL, category
253: .getCategoryId());
254:
255: // Category
256:
257: mbCategoryPersistence.remove(category.getCategoryId());
258: }
259:
260: public List getCategories(long groupId, long parentCategoryId,
261: int begin, int end) throws SystemException {
262:
263: return mbCategoryPersistence.findByG_P(groupId,
264: parentCategoryId, begin, end);
265: }
266:
267: public int getCategoriesCount(long groupId) throws SystemException {
268: return mbCategoryPersistence.countByGroupId(groupId);
269: }
270:
271: public int getCategoriesCount(long groupId, long parentCategoryId)
272: throws SystemException {
273:
274: return mbCategoryPersistence.countByG_P(groupId,
275: parentCategoryId);
276: }
277:
278: public MBCategory getCategory(long categoryId)
279: throws PortalException, SystemException {
280:
281: return mbCategoryPersistence.findByPrimaryKey(categoryId);
282: }
283:
284: public void getSubcategoryIds(List categoryIds, long groupId,
285: long categoryId) throws SystemException {
286:
287: Iterator itr = mbCategoryPersistence.findByG_P(groupId,
288: categoryId).iterator();
289:
290: while (itr.hasNext()) {
291: MBCategory category = (MBCategory) itr.next();
292:
293: categoryIds.add(new Long(category.getCategoryId()));
294:
295: getSubcategoryIds(categoryIds, category.getGroupId(),
296: category.getCategoryId());
297: }
298: }
299:
300: public List getSubscribedCategories(long groupId, long userId,
301: int begin, int end) throws SystemException {
302:
303: return mbCategoryFinder
304: .findByS_G_U(groupId, userId, begin, end);
305: }
306:
307: public int getSubscribedCategoriesCount(long groupId, long userId)
308: throws SystemException {
309:
310: return mbCategoryFinder.countByS_G_U(groupId, userId);
311: }
312:
313: public MBCategory getSystemCategory() throws PortalException,
314: SystemException {
315:
316: long categoryId = CompanyImpl.SYSTEM;
317:
318: MBCategory category = mbCategoryPersistence
319: .fetchByPrimaryKey(categoryId);
320:
321: if (category == null) {
322: category = mbCategoryPersistence.create(categoryId);
323:
324: category.setCompanyId(CompanyImpl.SYSTEM);
325: category.setUserId(CompanyImpl.SYSTEM);
326:
327: mbCategoryPersistence.update(category);
328: }
329:
330: return category;
331: }
332:
333: public void reIndex(String[] ids) throws SystemException {
334: if (LuceneUtil.INDEX_READ_ONLY) {
335: return;
336: }
337:
338: long companyId = GetterUtil.getLong(ids[0]);
339:
340: IndexWriter writer = null;
341:
342: try {
343: writer = LuceneUtil.getWriter(companyId);
344:
345: Iterator itr1 = mbCategoryPersistence.findByCompanyId(
346: companyId).iterator();
347:
348: while (itr1.hasNext()) {
349: MBCategory category = (MBCategory) itr1.next();
350:
351: long categoryId = category.getCategoryId();
352:
353: Iterator itr2 = mbMessagePersistence.findByCategoryId(
354: categoryId).iterator();
355:
356: while (itr2.hasNext()) {
357: MBMessage message = (MBMessage) itr2.next();
358:
359: long groupId = category.getGroupId();
360: String userName = message.getUserName();
361: long threadId = message.getThreadId();
362: long messageId = message.getMessageId();
363: String title = message.getSubject();
364: String content = message.getBody();
365:
366: String[] tagsEntries = tagsEntryLocalService
367: .getEntryNames(MBMessage.class.getName(),
368: messageId);
369:
370: try {
371: Document doc = Indexer.getAddMessageDocument(
372: companyId, groupId, userName,
373: categoryId, threadId, messageId, title,
374: content, tagsEntries);
375:
376: writer.addDocument(doc);
377: } catch (Exception e1) {
378: _log.error("Reindexing " + messageId, e1);
379: }
380: }
381: }
382: } catch (SystemException se) {
383: throw se;
384: } catch (Exception e2) {
385: throw new SystemException(e2);
386: } finally {
387: try {
388: if (writer != null) {
389: LuceneUtil.write(companyId);
390: }
391: } catch (Exception e) {
392: _log.error(e);
393: }
394: }
395: }
396:
397: public Hits search(long companyId, long groupId,
398: long[] categoryIds, long threadId, String keywords)
399: throws SystemException {
400:
401: Searcher searcher = null;
402:
403: try {
404: HitsImpl hits = new HitsImpl();
405:
406: BooleanQuery contextQuery = new BooleanQuery();
407:
408: LuceneUtil.addRequiredTerm(contextQuery,
409: LuceneFields.PORTLET_ID, Indexer.PORTLET_ID);
410:
411: if (groupId > 0) {
412: LuceneUtil.addRequiredTerm(contextQuery,
413: LuceneFields.GROUP_ID, groupId);
414: }
415:
416: if ((categoryIds != null) && (categoryIds.length > 0)) {
417: BooleanQuery categoryIdsQuery = new BooleanQuery();
418:
419: for (int i = 0; i < categoryIds.length; i++) {
420: Term term = new Term("categoryId", String
421: .valueOf(categoryIds[i]));
422: TermQuery termQuery = new TermQuery(term);
423:
424: categoryIdsQuery.add(termQuery,
425: BooleanClause.Occur.SHOULD);
426: }
427:
428: contextQuery.add(categoryIdsQuery,
429: BooleanClause.Occur.MUST);
430: }
431:
432: if (threadId > 0) {
433: LuceneUtil.addTerm(contextQuery, "threadId", threadId);
434: }
435:
436: BooleanQuery searchQuery = new BooleanQuery();
437:
438: if (Validator.isNotNull(keywords)) {
439: LuceneUtil.addTerm(searchQuery, LuceneFields.USER_NAME,
440: keywords);
441: LuceneUtil.addTerm(searchQuery, LuceneFields.TITLE,
442: keywords);
443: LuceneUtil.addTerm(searchQuery, LuceneFields.CONTENT,
444: keywords);
445: LuceneUtil.addTerm(searchQuery, LuceneFields.TAG_ENTRY,
446: keywords);
447: }
448:
449: BooleanQuery fullQuery = new BooleanQuery();
450:
451: fullQuery.add(contextQuery, BooleanClause.Occur.MUST);
452:
453: if (searchQuery.clauses().size() > 0) {
454: fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
455: }
456:
457: searcher = LuceneUtil.getSearcher(companyId);
458:
459: hits.recordHits(searcher.search(fullQuery), searcher);
460:
461: return hits;
462: } catch (Exception e) {
463: return LuceneUtil.closeSearcher(searcher, keywords, e);
464: }
465: }
466:
467: public MBCategory updateCategory(long categoryId,
468: long parentCategoryId, String name, String description,
469: boolean mergeWithParentCategory) throws PortalException,
470: SystemException {
471:
472: // Category
473:
474: MBCategory category = mbCategoryPersistence
475: .findByPrimaryKey(categoryId);
476:
477: parentCategoryId = getParentCategoryId(category,
478: parentCategoryId);
479:
480: validate(name);
481:
482: category.setModifiedDate(new Date());
483: category.setParentCategoryId(parentCategoryId);
484: category.setName(name);
485: category.setDescription(description);
486:
487: mbCategoryPersistence.update(category);
488:
489: // Merge categories
490:
491: if (mergeWithParentCategory
492: && (categoryId != parentCategoryId)
493: && (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID)) {
494:
495: mergeCategories(category, parentCategoryId);
496: }
497:
498: return category;
499: }
500:
501: protected long getParentCategoryId(long groupId,
502: long parentCategoryId) throws SystemException {
503:
504: if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
505: MBCategory parentCategory = mbCategoryPersistence
506: .fetchByPrimaryKey(parentCategoryId);
507:
508: if ((parentCategory == null)
509: || (groupId != parentCategory.getGroupId())) {
510:
511: parentCategoryId = MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID;
512: }
513: }
514:
515: return parentCategoryId;
516: }
517:
518: protected long getParentCategoryId(MBCategory category,
519: long parentCategoryId) throws SystemException {
520:
521: if (parentCategoryId == MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
522: return parentCategoryId;
523: }
524:
525: if (category.getCategoryId() == parentCategoryId) {
526: return category.getParentCategoryId();
527: } else {
528: MBCategory parentCategory = mbCategoryPersistence
529: .fetchByPrimaryKey(parentCategoryId);
530:
531: if ((parentCategory == null)
532: || (category.getGroupId() != parentCategory
533: .getGroupId())) {
534:
535: return category.getParentCategoryId();
536: }
537:
538: List subcategoryIds = new ArrayList();
539:
540: getSubcategoryIds(subcategoryIds, category.getGroupId(),
541: category.getCategoryId());
542:
543: if (subcategoryIds.contains(new Long(parentCategoryId))) {
544: return category.getParentCategoryId();
545: }
546:
547: return parentCategoryId;
548: }
549: }
550:
551: protected void mergeCategories(MBCategory fromCategory,
552: long toCategoryId) throws PortalException, SystemException {
553:
554: Iterator itr = mbCategoryPersistence
555: .findByG_P(fromCategory.getGroupId(),
556: fromCategory.getCategoryId()).iterator();
557:
558: while (itr.hasNext()) {
559: MBCategory category = (MBCategory) itr.next();
560:
561: mergeCategories(category, toCategoryId);
562: }
563:
564: Iterator itr1 = mbThreadPersistence.findByCategoryId(
565: fromCategory.getCategoryId()).iterator();
566:
567: while (itr1.hasNext()) {
568:
569: // Thread
570:
571: MBThread thread = (MBThread) itr1.next();
572:
573: thread.setCategoryId(toCategoryId);
574:
575: mbThreadPersistence.update(thread);
576:
577: Iterator itr2 = mbMessagePersistence.findByThreadId(
578: thread.getThreadId()).iterator();
579:
580: while (itr2.hasNext()) {
581:
582: // Message
583:
584: MBMessage message = (MBMessage) itr2.next();
585:
586: message.setCategoryId(toCategoryId);
587:
588: mbMessagePersistence.update(message);
589:
590: // Lucene
591:
592: try {
593: if (!fromCategory.isDiscussion()) {
594: String[] tagsEntries = tagsEntryLocalService
595: .getEntryNames(MBMessage.class
596: .getName(), message
597: .getMessageId());
598:
599: Indexer.updateMessage(message.getCompanyId(),
600: fromCategory.getGroupId(), message
601: .getUserName(), toCategoryId,
602: message.getThreadId(), message
603: .getMessageId(), message
604: .getSubject(), message
605: .getBody(), tagsEntries);
606: }
607: } catch (IOException ioe) {
608: _log.error("Indexing " + message.getMessageId(),
609: ioe);
610: }
611: }
612: }
613:
614: mbCategoryPersistence.remove(fromCategory.getCategoryId());
615: }
616:
617: public void subscribeCategory(long userId, long categoryId)
618: throws PortalException, SystemException {
619:
620: subscriptionLocalService.addSubscription(userId,
621: MBCategory.class.getName(), categoryId);
622: }
623:
624: public void unsubscribeCategory(long userId, long categoryId)
625: throws PortalException, SystemException {
626:
627: subscriptionLocalService.deleteSubscription(userId,
628: 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 = LogFactory
638: .getLog(MBCategoryLocalServiceImpl.class);
639:
640: }
|