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