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