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