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             exportParentCategory(
268                 context, categoriesEl, category.getParentCategoryId());
269 
270             String path = getCategoryPath(context, category);
271 
272             if (context.isPathNotProcessed(path)) {
273                 Element categoryEl = categoriesEl.addElement("category");
274 
275                 categoryEl.addAttribute("path", path);
276 
277                 category.setUserUuid(category.getUserUuid());
278 
279                 context.addZipEntry(path, category);
280             }
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         exportParentCategory(context, categoriesEl, message.getCategoryId());
302 
303         String path = getMessagePath(context, message);
304 
305         if (context.isPathNotProcessed(path)) {
306             Element messageEl = messagesEl.addElement("message");
307 
308             messageEl.addAttribute("path", path);
309 
310             message.setUserUuid(message.getUserUuid());
311             message.setPriority(message.getPriority());
312 
313             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
314                 context.addRatingsEntries(
315                     MBMessage.class, message.getMessageId());
316             }
317 
318             if (context.getBooleanParameter(_NAMESPACE, "tags")) {
319                 context.addTagsEntries(
320                     MBMessage.class, message.getMessageId());
321             }
322 
323             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
324                 message.isAttachments()) {
325 
326                 for (String attachment : message.getAttachmentsFiles()) {
327                     int pos = attachment.lastIndexOf(StringPool.FORWARD_SLASH);
328 
329                     String name = attachment.substring(pos + 1);
330                     String binPath = getMessageAttachementBinPath(
331                         context, message, name);
332 
333                     Element attachmentEl = messageEl.addElement("attachment");
334 
335                     attachmentEl.addAttribute("name", name);
336                     attachmentEl.addAttribute("bin-path", binPath);
337 
338                     try {
339                         byte[] bytes = DLServiceUtil.getFile(
340                             context.getCompanyId(), CompanyConstants.SYSTEM,
341                             attachment);
342 
343                         context.addZipEntry(binPath, bytes);
344                     }
345                     catch (RemoteException re) {
346                     }
347                 }
348 
349                 message.setAttachmentsDir(message.getAttachmentsDir());
350             }
351 
352             if (context.getBooleanParameter(_NAMESPACE, "flags")) {
353                 List<MBMessageFlag> messageFlags =
354                     MBMessageFlagUtil.findByMessageId(
355                         message.getMessageId());
356 
357                 for (MBMessageFlag messageFlag : messageFlags) {
358                     exportMessageFlag(context, messageFlagsEl, messageFlag);
359                 }
360             }
361 
362             context.addZipEntry(path, message);
363         }
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         exportParentCategory(
399             context, categoriesEl, category.getParentCategoryId());
400 
401         String path = getCategoryPath(context, category);
402 
403         if (context.isPathNotProcessed(path)) {
404             Element categoryEl = categoriesEl.addElement("category");
405 
406             categoryEl.addAttribute("path", path);
407 
408             category.setUserUuid(category.getUserUuid());
409 
410             context.addZipEntry(path, category);
411         }
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         if ((parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) &&
474             (parentCategoryId == category.getParentCategoryId())) {
475 
476             String path = getImportCategoryPath(context, parentCategoryId);
477 
478             MBCategory parentCategory =
479                 (MBCategory)context.getZipEntryAsObject(path);
480 
481             importCategory(context, categoryPKs, parentCategory);
482 
483             parentCategoryId = MapUtil.getLong(
484                 categoryPKs, category.getParentCategoryId(),
485                 category.getParentCategoryId());
486         }
487 
488         MBCategory existingCategory = null;
489 
490         try {
491             if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
492                 MBCategoryUtil.findByPrimaryKey(parentCategoryId);
493             }
494 
495             if (context.getDataStrategy().equals(
496                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
497 
498                 existingCategory = MBCategoryUtil.fetchByUUID_G(
499                     category.getUuid(), context.getGroupId());
500 
501                 if (existingCategory == null) {
502                     existingCategory = MBCategoryLocalServiceUtil.addCategory(
503                         category.getUuid(), userId, plid, parentCategoryId,
504                         category.getName(), category.getDescription(),
505                         addCommunityPermissions, addGuestPermissions);
506                 }
507                 else {
508                     existingCategory =
509                         MBCategoryLocalServiceUtil.updateCategory(
510                             existingCategory.getCategoryId(), parentCategoryId,
511                             category.getName(), category.getDescription(),
512                             false);
513                 }
514             }
515             else {
516                 existingCategory = MBCategoryLocalServiceUtil.addCategory(
517                     userId, plid, parentCategoryId, category.getName(),
518                     category.getDescription(), addCommunityPermissions,
519                     addGuestPermissions);
520             }
521 
522             categoryPKs.put(
523                 category.getCategoryId(), existingCategory.getCategoryId());
524         }
525         catch (NoSuchCategoryException nsce) {
526             _log.error(
527                 "Could not find the parent category for category " +
528                     category.getCategoryId());
529         }
530     }
531 
532     protected void importFlag(
533             PortletDataContext context, Map<Long, Long> messagePKs,
534             MBMessageFlag flag)
535         throws Exception {
536 
537         long userId = context.getUserId(flag.getUserUuid());
538         long messageId = MapUtil.getLong(
539             messagePKs, flag.getMessageId(), flag.getMessageId());
540 
541         try {
542             List<MBMessage> messages = new ArrayList<MBMessage>();
543 
544             messages.add(MBMessageUtil.findByPrimaryKey(messageId));
545 
546             MBMessageFlagLocalServiceUtil.addReadFlags(userId, messages);
547         }
548         catch (NoSuchMessageException nsme) {
549             _log.error(
550                 "Could not find the message for flag " +
551                     flag.getMessageFlagId());
552         }
553     }
554 
555     protected void importMessage(
556             PortletDataContext context, Map<Long, Long> categoryPKs,
557             Map<Long, Long> threadPKs, Map<Long, Long> messagePKs,
558             Element messageEl, MBMessage message)
559         throws Exception {
560 
561         long userId = context.getUserId(message.getUserUuid());
562         String userName = message.getUserName();
563         long categoryId = MapUtil.getLong(
564             categoryPKs, message.getCategoryId(), message.getCategoryId());
565         long threadId = MapUtil.getLong(
566             threadPKs, message.getThreadId(), message.getThreadId());
567         long parentMessageId = MapUtil.getLong(
568             messagePKs, message.getParentMessageId(),
569             message.getParentMessageId());
570 
571         List<ObjectValuePair<String, byte[]>> files =
572             new ArrayList<ObjectValuePair<String, byte[]>>();
573         List<String> existingFiles = new ArrayList<String>();
574 
575         if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
576             message.isAttachments()) {
577 
578             List<Element> attachmentEls = messageEl.elements("attachment");
579 
580             for (Element attachmentEl : attachmentEls) {
581                 String name = attachmentEl.attributeValue("name");
582                 String binPath = attachmentEl.attributeValue("bin-path");
583 
584                 byte[] bytes = context.getZipEntryAsByteArray(binPath);
585 
586                 files.add(new ObjectValuePair<String, byte[]>(name, bytes));
587             }
588 
589             if (files.size() <= 0) {
590                 _log.error(
591                     "Could not find attachments for message " +
592                         message.getMessageId());
593             }
594         }
595 
596         String[] tagsEntries = null;
597 
598         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
599             tagsEntries = context.getTagsEntries(
600                 MBMessage.class, message.getMessageId());
601         }
602 
603         PortletPreferences prefs = null;
604 
605         boolean addCommunityPermissions = true;
606         boolean addGuestPermissions = true;
607 
608         ThemeDisplay themeDisplay = null;
609 
610         if ((categoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) &&
611             (categoryId == message.getCategoryId())) {
612 
613             String path = getImportCategoryPath(context, categoryId);
614 
615             MBCategory category = (MBCategory)context.getZipEntryAsObject(path);
616 
617             importCategory(context, categoryPKs, category);
618 
619             categoryId = MapUtil.getLong(
620                 categoryPKs, message.getCategoryId(), message.getCategoryId());
621         }
622 
623         MBMessage existingMessage = null;
624 
625         try {
626             MBCategoryUtil.findByPrimaryKey(categoryId);
627 
628             if (parentMessageId != MBMessageImpl.DEFAULT_PARENT_MESSAGE_ID) {
629                 MBMessageUtil.findByPrimaryKey(parentMessageId);
630                 MBThreadUtil.findByPrimaryKey(threadId);
631             }
632 
633             if (context.getDataStrategy().equals(
634                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
635 
636                 try {
637                     existingMessage = MBMessageFinderUtil.findByUuid_G(
638                         message.getUuid(), context.getGroupId());
639 
640                     MBMessageLocalServiceUtil.updateMessage(
641                         userId, existingMessage.getMessageId(),
642                         message.getSubject(), message.getBody(), files,
643                         existingFiles, message.getPriority(), tagsEntries,
644                         prefs, themeDisplay);
645                 }
646                 catch (NoSuchMessageException nsme) {
647                     existingMessage = MBMessageLocalServiceUtil.addMessage(
648                         message.getUuid(), userId, userName, categoryId,
649                         threadId, parentMessageId, message.getSubject(),
650                         message.getBody(), files, message.getAnonymous(),
651                         message.getPriority(), tagsEntries, prefs,
652                         addCommunityPermissions, addGuestPermissions,
653                         themeDisplay);
654                 }
655             }
656             else {
657                 existingMessage = MBMessageLocalServiceUtil.addMessage(
658                     userId, userName, categoryId, threadId, parentMessageId,
659                     message.getSubject(), message.getBody(), files,
660                     message.getAnonymous(), message.getPriority(), tagsEntries,
661                     prefs, addCommunityPermissions, addGuestPermissions,
662                     themeDisplay);
663             }
664 
665             threadPKs.put(message.getThreadId(), existingMessage.getThreadId());
666             messagePKs.put(
667                 message.getMessageId(), existingMessage.getMessageId());
668 
669             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
670                 context.importRatingsEntries(
671                     MBMessage.class, message.getMessageId(),
672                     existingMessage.getMessageId());
673             }
674         }
675         catch (NoSuchCategoryException nsce) {
676             _log.error(
677                 "Could not find the parent category for message " +
678                     message.getMessageId());
679         }
680         catch (NoSuchMessageException nsme) {
681             _log.error(
682                 "Could not find the parent message for message " +
683                     message.getMessageId());
684         }
685         catch (NoSuchThreadException nste) {
686             _log.error(
687                 "Could not find the thread for message " +
688                     message.getMessageId());
689         }
690     }
691 
692     protected String getCategoryPath(
693         PortletDataContext context, MBCategory category) {
694 
695         StringBuilder sb = new StringBuilder();
696 
697         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
698         sb.append("/categories/");
699         sb.append(category.getCategoryId());
700         sb.append(".xml");
701 
702         return sb.toString();
703     }
704 
705     protected String getImportCategoryPath(
706         PortletDataContext context, long categoryId) {
707 
708         StringBuilder sb = new StringBuilder();
709 
710         sb.append(context.getImportPortletPath(PortletKeys.MESSAGE_BOARDS));
711         sb.append("/categories/");
712         sb.append(categoryId);
713         sb.append(".xml");
714 
715         return sb.toString();
716     }
717 
718     protected String getMessageAttachementBinPath(
719         PortletDataContext context, MBMessage message, String attachment) {
720 
721         StringBuilder sb = new StringBuilder();
722 
723         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
724         sb.append("/bin/");
725         sb.append(message.getMessageId());
726         sb.append(StringPool.SLASH);
727         sb.append(attachment);
728 
729         return sb.toString();
730     }
731 
732     protected String getMessageFlagPath(
733         PortletDataContext context, MBMessageFlag messageFlag) {
734 
735         StringBuilder sb = new StringBuilder();
736 
737         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
738         sb.append("/message-flags/");
739         sb.append(messageFlag.getMessageFlagId());
740         sb.append(".xml");
741 
742         return sb.toString();
743     }
744 
745     protected String getMessagePath(
746         PortletDataContext context, MBMessage message) {
747 
748         StringBuilder sb = new StringBuilder();
749 
750         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
751         sb.append("/messages/");
752         sb.append(message.getMessageId());
753         sb.append(".xml");
754 
755         return sb.toString();
756     }
757 
758     protected String getUserBanPath(PortletDataContext context, MBBan ban) {
759         StringBuilder sb = new StringBuilder();
760 
761         sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
762         sb.append("/user-bans/");
763         sb.append(ban.getBanId());
764         sb.append(".xml");
765 
766         return sb.toString();
767     }
768 
769     private static final String _NAMESPACE = "message_board";
770 
771     private static final PortletDataHandlerBoolean _categoriesAndMessages =
772         new PortletDataHandlerBoolean(
773             _NAMESPACE, "categories-and-messages", true, true);
774 
775     private static final PortletDataHandlerBoolean _attachments =
776         new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
777 
778     private static final PortletDataHandlerBoolean _userBans =
779         new PortletDataHandlerBoolean(_NAMESPACE, "user-bans");
780 
781     private static final PortletDataHandlerBoolean _flags =
782         new PortletDataHandlerBoolean(_NAMESPACE, "flags");
783 
784     private static final PortletDataHandlerBoolean _ratings =
785         new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
786 
787     private static final PortletDataHandlerBoolean _tags =
788         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
789 
790     private static Log _log =
791         LogFactory.getLog(MBPortletDataHandlerImpl.class);
792 
793 }