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