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.lar;
16  
17  import com.liferay.documentlibrary.service.DLServiceUtil;
18  import com.liferay.portal.PortalException;
19  import com.liferay.portal.SystemException;
20  import com.liferay.portal.kernel.log.Log;
21  import com.liferay.portal.kernel.log.LogFactoryUtil;
22  import com.liferay.portal.kernel.util.MapUtil;
23  import com.liferay.portal.kernel.util.ObjectValuePair;
24  import com.liferay.portal.kernel.util.StringBundler;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.xml.Document;
27  import com.liferay.portal.kernel.xml.Element;
28  import com.liferay.portal.kernel.xml.SAXReaderUtil;
29  import com.liferay.portal.lar.PortletDataContext;
30  import com.liferay.portal.lar.PortletDataException;
31  import com.liferay.portal.lar.PortletDataHandler;
32  import com.liferay.portal.lar.PortletDataHandlerBoolean;
33  import com.liferay.portal.lar.PortletDataHandlerControl;
34  import com.liferay.portal.lar.PortletDataHandlerKeys;
35  import com.liferay.portal.model.CompanyConstants;
36  import com.liferay.portal.model.User;
37  import com.liferay.portal.service.persistence.UserUtil;
38  import com.liferay.portal.theme.ThemeDisplay;
39  import com.liferay.portal.util.PortletKeys;
40  import com.liferay.portlet.messageboards.NoSuchCategoryException;
41  import com.liferay.portlet.messageboards.NoSuchMessageException;
42  import com.liferay.portlet.messageboards.NoSuchThreadException;
43  import com.liferay.portlet.messageboards.model.MBBan;
44  import com.liferay.portlet.messageboards.model.MBCategory;
45  import com.liferay.portlet.messageboards.model.MBMessage;
46  import com.liferay.portlet.messageboards.model.MBMessageFlag;
47  import com.liferay.portlet.messageboards.model.MBThread;
48  import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
49  import com.liferay.portlet.messageboards.model.impl.MBMessageImpl;
50  import com.liferay.portlet.messageboards.service.MBBanLocalServiceUtil;
51  import com.liferay.portlet.messageboards.service.MBCategoryLocalServiceUtil;
52  import com.liferay.portlet.messageboards.service.MBMessageFlagLocalServiceUtil;
53  import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
54  import com.liferay.portlet.messageboards.service.persistence.MBBanUtil;
55  import com.liferay.portlet.messageboards.service.persistence.MBCategoryUtil;
56  import com.liferay.portlet.messageboards.service.persistence.MBMessageFlagUtil;
57  import com.liferay.portlet.messageboards.service.persistence.MBMessageUtil;
58  import com.liferay.portlet.messageboards.service.persistence.MBThreadUtil;
59  
60  import java.rmi.RemoteException;
61  
62  import java.util.ArrayList;
63  import java.util.Iterator;
64  import java.util.List;
65  import java.util.Map;
66  
67  import javax.portlet.PortletPreferences;
68  
69  /**
70   * <a href="MBPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
71   *
72   * @author Bruno Farache
73   * @author Raymond Augé
74   */
75  public class MBPortletDataHandlerImpl implements PortletDataHandler {
76  
77      public PortletPreferences deleteData(
78              PortletDataContext context, String portletId,
79              PortletPreferences prefs)
80          throws PortletDataException {
81  
82          try {
83              if (!context.addPrimaryKey(
84                      MBPortletDataHandlerImpl.class, "deleteData")) {
85  
86                  MBCategoryLocalServiceUtil.deleteCategories(
87                      context.getGroupId());
88              }
89  
90              return null;
91          }
92          catch (Exception e) {
93              throw new PortletDataException(e);
94          }
95      }
96  
97      public String exportData(
98              PortletDataContext context, String portletId,
99              PortletPreferences prefs)
100         throws PortletDataException {
101 
102         try {
103             Document doc = SAXReaderUtil.createDocument();
104 
105             Element root = doc.addElement("message-boards-data");
106 
107             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
108 
109             Element categoriesEl = root.addElement("categories");
110             Element messagesEl = root.addElement("messages");
111             Element messageFlagsEl = root.addElement("message-flags");
112             Element userBansEl = root.addElement("user-bans");
113 
114             List<MBCategory> categories = MBCategoryUtil.findByGroupId(
115                 context.getGroupId());
116 
117             for (MBCategory category : categories) {
118                 exportCategory(
119                     context, categoriesEl, messagesEl, messageFlagsEl,
120                     category);
121             }
122 
123             if (context.getBooleanParameter(_NAMESPACE, "user-bans")) {
124                 List<MBBan> bans = MBBanUtil.findByGroupId(
125                     context.getGroupId());
126 
127                 for (MBBan ban : bans) {
128                     exportUserBan(context, userBansEl, ban);
129                 }
130             }
131 
132             return doc.formattedString();
133         }
134         catch (Exception e) {
135             throw new PortletDataException(e);
136         }
137     }
138 
139     public PortletDataHandlerControl[] getExportControls() {
140         return new PortletDataHandlerControl[] {
141             _categoriesAndMessages, _attachments, _userBans, _flags, _ratings,
142             _tags
143         };
144     }
145 
146     public PortletDataHandlerControl[] getImportControls() {
147         return new PortletDataHandlerControl[] {
148             _categoriesAndMessages, _attachments, _userBans, _flags, _ratings,
149             _tags
150         };
151     }
152 
153     public PortletPreferences importData(
154             PortletDataContext context, String portletId,
155             PortletPreferences prefs, String data)
156         throws PortletDataException {
157 
158         try {
159             Document doc = SAXReaderUtil.read(data);
160 
161             Element root = doc.getRootElement();
162 
163             List<Element> categoryEls = root.element("categories").elements(
164                 "category");
165 
166             Map<Long, Long> categoryPKs =
167                 (Map<Long, Long>)context.getNewPrimaryKeysMap(MBCategory.class);
168 
169             for (Element categoryEl : categoryEls) {
170                 String path = categoryEl.attributeValue("path");
171 
172                 if (!context.isPathNotProcessed(path)) {
173                     continue;
174                 }
175 
176                 MBCategory category = (MBCategory)context.getZipEntryAsObject(
177                     path);
178 
179                 importCategory(context, categoryPKs, category);
180             }
181 
182             List<Element> messageEls = root.element("messages").elements(
183                 "message");
184 
185             Map<Long, Long> threadPKs =
186                 (Map<Long, Long>)context.getNewPrimaryKeysMap(MBThread.class);
187             Map<Long, Long> messagePKs =
188                 (Map<Long, Long>)context.getNewPrimaryKeysMap(MBMessage.class);
189 
190             for (Element messageEl : messageEls) {
191                 String path = messageEl.attributeValue("path");
192 
193                 if (!context.isPathNotProcessed(path)) {
194                     continue;
195                 }
196 
197                 MBMessage message = (MBMessage)context.getZipEntryAsObject(
198                     path);
199 
200                 importMessage(
201                     context, categoryPKs, threadPKs, messagePKs, messageEl,
202                     message);
203             }
204 
205             if (context.getBooleanParameter(_NAMESPACE, "flags")) {
206                 List<Element> flagEls = root.element("message-flags").elements(
207                     "flag");
208 
209                 for (Element flagEl : flagEls) {
210                     String path = flagEl.attributeValue("path");
211 
212                     if (!context.isPathNotProcessed(path)) {
213                         continue;
214                     }
215 
216                     MBMessageFlag flag =
217                         (MBMessageFlag)context.getZipEntryAsObject(path);
218 
219                     importFlag(context, messagePKs, flag);
220                 }
221             }
222 
223             if (context.getBooleanParameter(_NAMESPACE, "user-bans")) {
224                 List<Element> banEls = root.element("user-bans").elements(
225                     "user-ban");
226 
227                 for (Element banEl : banEls) {
228                     String path = banEl.attributeValue("path");
229 
230                     if (!context.isPathNotProcessed(path)) {
231                         continue;
232                     }
233 
234                     MBBan ban = (MBBan)context.getZipEntryAsObject(path);
235 
236                     importBan(context, ban);
237                 }
238             }
239 
240             return null;
241         }
242         catch (Exception e) {
243             throw new PortletDataException(e);
244         }
245     }
246 
247     public boolean isPublishToLiveByDefault() {
248         return false;
249     }
250 
251     protected void exportCategory(
252             PortletDataContext context, Element categoriesEl,
253             Element messagesEl, Element messageFlagsEl, MBCategory category)
254         throws PortalException, SystemException {
255 
256         if (context.isWithinDateRange(category.getModifiedDate())) {
257             exportParentCategory(
258                 context, categoriesEl, category.getParentCategoryId());
259 
260             String path = getCategoryPath(context, category);
261 
262             if (context.isPathNotProcessed(path)) {
263                 Element categoryEl = categoriesEl.addElement("category");
264 
265                 categoryEl.addAttribute("path", path);
266 
267                 category.setUserUuid(category.getUserUuid());
268 
269                 context.addZipEntry(path, category);
270             }
271         }
272 
273         List<MBMessage> messages = MBMessageUtil.findByCategoryId(
274             category.getCategoryId());
275 
276         for (MBMessage message : messages) {
277             exportMessage(
278                 context, categoriesEl, messagesEl, messageFlagsEl, message);
279         }
280     }
281 
282     protected void exportMessage(
283             PortletDataContext context, Element categoriesEl,
284             Element messagesEl, Element messageFlagsEl, MBMessage message)
285         throws PortalException, SystemException {
286 
287         if (!context.isWithinDateRange(message.getModifiedDate())) {
288             return;
289         }
290 
291         exportParentCategory(context, categoriesEl, message.getCategoryId());
292 
293         String path = getMessagePath(context, message);
294 
295         if (context.isPathNotProcessed(path)) {
296             Element messageEl = messagesEl.addElement("message");
297 
298             messageEl.addAttribute("path", path);
299 
300             message.setUserUuid(message.getUserUuid());
301             message.setPriority(message.getPriority());
302 
303             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
304                 context.addRatingsEntries(
305                     MBMessage.class, message.getMessageId());
306             }
307 
308             if (context.getBooleanParameter(_NAMESPACE, "tags")) {
309                 context.addTagsEntries(
310                     MBMessage.class, message.getMessageId());
311             }
312 
313             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
314                 message.isAttachments()) {
315 
316                 for (String attachment : message.getAttachmentsFiles()) {
317                     int pos = attachment.lastIndexOf(StringPool.FORWARD_SLASH);
318 
319                     String name = attachment.substring(pos + 1);
320                     String binPath = getMessageAttachementBinPath(
321                         context, message, name);
322 
323                     Element attachmentEl = messageEl.addElement("attachment");
324 
325                     attachmentEl.addAttribute("name", name);
326                     attachmentEl.addAttribute("bin-path", binPath);
327 
328                     try {
329                         byte[] bytes = DLServiceUtil.getFile(
330                             context.getCompanyId(), CompanyConstants.SYSTEM,
331                             attachment);
332 
333                         context.addZipEntry(binPath, bytes);
334                     }
335                     catch (RemoteException re) {
336                     }
337                 }
338 
339                 message.setAttachmentsDir(message.getAttachmentsDir());
340             }
341 
342             if (context.getBooleanParameter(_NAMESPACE, "flags")) {
343                 List<MBMessageFlag> messageFlags =
344                     MBMessageFlagUtil.findByMessageId(
345                         message.getMessageId());
346 
347                 for (MBMessageFlag messageFlag : messageFlags) {
348                     exportMessageFlag(context, messageFlagsEl, messageFlag);
349                 }
350             }
351 
352             context.addZipEntry(path, message);
353         }
354     }
355 
356     protected void exportMessageFlag(
357             PortletDataContext context, Element messageFlagsEl,
358             MBMessageFlag messageFlag)
359         throws SystemException {
360 
361         String path = getMessageFlagPath(context, messageFlag);
362 
363         if (!context.isPathNotProcessed(path)) {
364             return;
365         }
366 
367         Element messageFlagEl = messageFlagsEl.addElement("message-flag");
368 
369         messageFlagEl.addAttribute("path", path);
370 
371         messageFlag.setUserUuid(messageFlag.getUserUuid());
372 
373         context.addZipEntry(path, messageFlag);
374     }
375 
376     protected void exportParentCategory(
377             PortletDataContext context, Element categoriesEl, long categoryId)
378         throws PortalException, SystemException {
379 
380         if ((!context.hasDateRange()) ||
381             (categoryId == MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID)) {
382 
383             return;
384         }
385 
386         MBCategory category = MBCategoryUtil.findByPrimaryKey(categoryId);
387 
388         exportParentCategory(
389             context, categoriesEl, category.getParentCategoryId());
390 
391         String path = getCategoryPath(context, category);
392 
393         if (context.isPathNotProcessed(path)) {
394             Element categoryEl = categoriesEl.addElement("category");
395 
396             categoryEl.addAttribute("path", path);
397 
398             category.setUserUuid(category.getUserUuid());
399 
400             context.addZipEntry(path, category);
401         }
402     }
403 
404     protected void exportUserBan(
405             PortletDataContext context, Element userBansEl, MBBan ban)
406         throws SystemException {
407 
408         if (!context.isWithinDateRange(ban.getModifiedDate())) {
409             return;
410         }
411 
412         String path = getUserBanPath(context, ban);
413 
414         if (!context.isPathNotProcessed(path)) {
415             return;
416         }
417 
418         Element userBanEl = userBansEl.addElement("user-ban");
419 
420         userBanEl.addAttribute("path", path);
421 
422         ban.setBanUserUuid(ban.getBanUserUuid());
423         ban.setUserUuid(ban.getUserUuid());
424 
425         context.addZipEntry(path, ban);
426     }
427 
428     protected void importBan(PortletDataContext context, MBBan ban)
429         throws Exception {
430 
431         long userId = context.getUserId(ban.getUserUuid());
432         long plid = context.getPlid();
433 
434         List<User> users = UserUtil.findByUuid(ban.getBanUserUuid());
435 
436         Iterator<User> itr = users.iterator();
437 
438         if (itr.hasNext()) {
439             User user = itr.next();
440 
441             MBBanLocalServiceUtil.addBan(userId, plid, user.getUserId());
442         }
443         else {
444             _log.error(
445                 "Could not find banned user with uuid " + ban.getBanUserUuid());
446         }
447     }
448 
449     protected void importCategory(
450             PortletDataContext context, Map<Long, Long> categoryPKs,
451             MBCategory category)
452         throws Exception {
453 
454         long userId = context.getUserId(category.getUserUuid());
455         long plid = context.getPlid();
456         long parentCategoryId = MapUtil.getLong(
457             categoryPKs, category.getParentCategoryId(),
458             category.getParentCategoryId());
459 
460         boolean addCommunityPermissions = true;
461         boolean addGuestPermissions = true;
462 
463         if ((parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) &&
464             (parentCategoryId == category.getParentCategoryId())) {
465 
466             String path = getImportCategoryPath(context, parentCategoryId);
467 
468             MBCategory parentCategory =
469                 (MBCategory)context.getZipEntryAsObject(path);
470 
471             importCategory(context, categoryPKs, parentCategory);
472 
473             parentCategoryId = MapUtil.getLong(
474                 categoryPKs, category.getParentCategoryId(),
475                 category.getParentCategoryId());
476         }
477 
478         MBCategory existingCategory = null;
479 
480         try {
481             if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
482                 MBCategoryUtil.findByPrimaryKey(parentCategoryId);
483             }
484 
485             if (context.getDataStrategy().equals(
486                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
487 
488                 existingCategory = MBCategoryUtil.fetchByUUID_G(
489                     category.getUuid(), context.getGroupId());
490 
491                 if (existingCategory == null) {
492                     existingCategory = MBCategoryLocalServiceUtil.addCategory(
493                         category.getUuid(), userId, plid, parentCategoryId,
494                         category.getName(), category.getDescription(),
495                         addCommunityPermissions, addGuestPermissions);
496                 }
497                 else {
498                     existingCategory =
499                         MBCategoryLocalServiceUtil.updateCategory(
500                             existingCategory.getCategoryId(), parentCategoryId,
501                             category.getName(), category.getDescription(),
502                             false);
503                 }
504             }
505             else {
506                 existingCategory = MBCategoryLocalServiceUtil.addCategory(
507                     userId, plid, parentCategoryId, category.getName(),
508                     category.getDescription(), addCommunityPermissions,
509                     addGuestPermissions);
510             }
511 
512             categoryPKs.put(
513                 category.getCategoryId(), existingCategory.getCategoryId());
514         }
515         catch (NoSuchCategoryException nsce) {
516             _log.error(
517                 "Could not find the parent category for category " +
518                     category.getCategoryId());
519         }
520     }
521 
522     protected void importFlag(
523             PortletDataContext context, Map<Long, Long> messagePKs,
524             MBMessageFlag flag)
525         throws Exception {
526 
527         long userId = context.getUserId(flag.getUserUuid());
528         long messageId = MapUtil.getLong(
529             messagePKs, flag.getMessageId(), flag.getMessageId());
530 
531         try {
532             MBMessage message = MBMessageUtil.findByPrimaryKey(messageId);
533 
534             MBThread thread = message.getThread();
535 
536             MBMessageFlagLocalServiceUtil.addReadFlags(userId, thread);
537         }
538         catch (NoSuchMessageException nsme) {
539             _log.error(
540                 "Could not find the message for flag " +
541                     flag.getMessageFlagId());
542         }
543     }
544 
545     protected void importMessage(
546             PortletDataContext context, Map<Long, Long> categoryPKs,
547             Map<Long, Long> threadPKs, Map<Long, Long> messagePKs,
548             Element messageEl, MBMessage message)
549         throws Exception {
550 
551         long userId = context.getUserId(message.getUserUuid());
552         String userName = message.getUserName();
553         long categoryId = MapUtil.getLong(
554             categoryPKs, message.getCategoryId(), message.getCategoryId());
555         long threadId = MapUtil.getLong(
556             threadPKs, message.getThreadId(), message.getThreadId());
557         long parentMessageId = MapUtil.getLong(
558             messagePKs, message.getParentMessageId(),
559             message.getParentMessageId());
560 
561         List<ObjectValuePair<String, byte[]>> files =
562             new ArrayList<ObjectValuePair<String, byte[]>>();
563         List<String> existingFiles = new ArrayList<String>();
564 
565         if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
566             message.isAttachments()) {
567 
568             List<Element> attachmentEls = messageEl.elements("attachment");
569 
570             for (Element attachmentEl : attachmentEls) {
571                 String name = attachmentEl.attributeValue("name");
572                 String binPath = attachmentEl.attributeValue("bin-path");
573 
574                 byte[] bytes = context.getZipEntryAsByteArray(binPath);
575 
576                 files.add(new ObjectValuePair<String, byte[]>(name, bytes));
577             }
578 
579             if (files.size() <= 0) {
580                 _log.error(
581                     "Could not find attachments for message " +
582                         message.getMessageId());
583             }
584         }
585 
586         String[] tagsEntries = null;
587 
588         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
589             tagsEntries = context.getTagsEntries(
590                 MBMessage.class, message.getMessageId());
591         }
592 
593         PortletPreferences prefs = null;
594 
595         boolean addCommunityPermissions = true;
596         boolean addGuestPermissions = true;
597 
598         ThemeDisplay themeDisplay = null;
599 
600         if ((categoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) &&
601             (categoryId == message.getCategoryId())) {
602 
603             String path = getImportCategoryPath(context, categoryId);
604 
605             MBCategory category = (MBCategory)context.getZipEntryAsObject(path);
606 
607             importCategory(context, categoryPKs, category);
608 
609             categoryId = MapUtil.getLong(
610                 categoryPKs, message.getCategoryId(), message.getCategoryId());
611         }
612 
613         MBMessage existingMessage = null;
614 
615         try {
616             MBCategoryUtil.findByPrimaryKey(categoryId);
617 
618             if (parentMessageId != MBMessageImpl.DEFAULT_PARENT_MESSAGE_ID) {
619                 MBMessageUtil.findByPrimaryKey(parentMessageId);
620                 MBThreadUtil.findByPrimaryKey(threadId);
621             }
622 
623             if (context.getDataStrategy().equals(
624                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
625 
626                 try {
627                     existingMessage = MBMessageUtil.findByUUID_G(
628                         message.getUuid(), context.getGroupId());
629 
630                     MBMessageLocalServiceUtil.updateMessage(
631                         userId, existingMessage.getMessageId(),
632                         message.getSubject(), message.getBody(), files,
633                         existingFiles, message.getPriority(), tagsEntries,
634                         prefs, themeDisplay);
635                 }
636                 catch (NoSuchMessageException nsme) {
637                     existingMessage = MBMessageLocalServiceUtil.addMessage(
638                         message.getUuid(), userId, userName, categoryId,
639                         threadId, parentMessageId, message.getSubject(),
640                         message.getBody(), files, message.getAnonymous(),
641                         message.getPriority(), tagsEntries, prefs,
642                         addCommunityPermissions, addGuestPermissions,
643                         themeDisplay);
644                 }
645             }
646             else {
647                 existingMessage = MBMessageLocalServiceUtil.addMessage(
648                     userId, userName, categoryId, threadId, parentMessageId,
649                     message.getSubject(), message.getBody(), files,
650                     message.getAnonymous(), message.getPriority(), tagsEntries,
651                     prefs, addCommunityPermissions, addGuestPermissions,
652                     themeDisplay);
653             }
654 
655             threadPKs.put(message.getThreadId(), existingMessage.getThreadId());
656             messagePKs.put(
657                 message.getMessageId(), existingMessage.getMessageId());
658 
659             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
660                 context.importRatingsEntries(
661                     MBMessage.class, message.getMessageId(),
662                     existingMessage.getMessageId());
663             }
664         }
665         catch (NoSuchCategoryException nsce) {
666             _log.error(
667                 "Could not find the parent category for message " +
668                     message.getMessageId());
669         }
670         catch (NoSuchMessageException nsme) {
671             _log.error(
672                 "Could not find the parent message for message " +
673                     message.getMessageId());
674         }
675         catch (NoSuchThreadException nste) {
676             _log.error(
677                 "Could not find the thread for message " +
678                     message.getMessageId());
679         }
680     }
681 
682     protected String getCategoryPath(
683         PortletDataContext context, MBCategory category) {
684 
685         StringBundler sb = new StringBundler(4);
686 
687         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
688         sb.append("/categories/");
689         sb.append(category.getCategoryId());
690         sb.append(".xml");
691 
692         return sb.toString();
693     }
694 
695     protected String getImportCategoryPath(
696         PortletDataContext context, long categoryId) {
697 
698         StringBundler sb = new StringBundler(4);
699 
700         sb.append(context.getImportPortletPath(PortletKeys.MESSAGE_BOARDS));
701         sb.append("/categories/");
702         sb.append(categoryId);
703         sb.append(".xml");
704 
705         return sb.toString();
706     }
707 
708     protected String getMessageAttachementBinPath(
709         PortletDataContext context, MBMessage message, String attachment) {
710 
711         StringBundler sb = new StringBundler(5);
712 
713         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
714         sb.append("/bin/");
715         sb.append(message.getMessageId());
716         sb.append(StringPool.SLASH);
717         sb.append(attachment);
718 
719         return sb.toString();
720     }
721 
722     protected String getMessageFlagPath(
723         PortletDataContext context, MBMessageFlag messageFlag) {
724 
725         StringBundler sb = new StringBundler(4);
726 
727         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
728         sb.append("/message-flags/");
729         sb.append(messageFlag.getMessageFlagId());
730         sb.append(".xml");
731 
732         return sb.toString();
733     }
734 
735     protected String getMessagePath(
736         PortletDataContext context, MBMessage message) {
737 
738         StringBundler sb = new StringBundler(4);
739 
740         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
741         sb.append("/messages/");
742         sb.append(message.getMessageId());
743         sb.append(".xml");
744 
745         return sb.toString();
746     }
747 
748     protected String getUserBanPath(PortletDataContext context, MBBan ban) {
749         StringBundler sb = new StringBundler(4);
750 
751         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
752         sb.append("/user-bans/");
753         sb.append(ban.getBanId());
754         sb.append(".xml");
755 
756         return sb.toString();
757     }
758 
759     private static final String _NAMESPACE = "message_board";
760 
761     private static final PortletDataHandlerBoolean _categoriesAndMessages =
762         new PortletDataHandlerBoolean(
763             _NAMESPACE, "categories-and-messages", true, true);
764 
765     private static final PortletDataHandlerBoolean _attachments =
766         new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
767 
768     private static final PortletDataHandlerBoolean _userBans =
769         new PortletDataHandlerBoolean(_NAMESPACE, "user-bans");
770 
771     private static final PortletDataHandlerBoolean _flags =
772         new PortletDataHandlerBoolean(_NAMESPACE, "flags");
773 
774     private static final PortletDataHandlerBoolean _ratings =
775         new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
776 
777     private static final PortletDataHandlerBoolean _tags =
778         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
779 
780     private static Log _log = LogFactoryUtil.getLog(
781         MBPortletDataHandlerImpl.class);
782 
783 }