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