001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.messageboards.lar;
016    
017    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
018    import com.liferay.portal.kernel.lar.PortletDataContext;
019    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.util.CharPool;
024    import com.liferay.portal.kernel.util.MapUtil;
025    import com.liferay.portal.kernel.util.ObjectValuePair;
026    import com.liferay.portal.kernel.util.StreamUtil;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
030    import com.liferay.portal.kernel.workflow.WorkflowConstants;
031    import com.liferay.portal.kernel.xml.Document;
032    import com.liferay.portal.kernel.xml.Element;
033    import com.liferay.portal.kernel.xml.SAXReaderUtil;
034    import com.liferay.portal.model.CompanyConstants;
035    import com.liferay.portal.model.User;
036    import com.liferay.portal.service.ServiceContext;
037    import com.liferay.portal.service.persistence.UserUtil;
038    import com.liferay.portal.util.PortletKeys;
039    import com.liferay.portal.util.PropsValues;
040    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
041    import com.liferay.portlet.messageboards.model.MBBan;
042    import com.liferay.portlet.messageboards.model.MBCategory;
043    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
044    import com.liferay.portlet.messageboards.model.MBMessage;
045    import com.liferay.portlet.messageboards.model.MBThread;
046    import com.liferay.portlet.messageboards.model.MBThreadFlag;
047    import com.liferay.portlet.messageboards.service.MBBanLocalServiceUtil;
048    import com.liferay.portlet.messageboards.service.MBCategoryLocalServiceUtil;
049    import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
050    import com.liferay.portlet.messageboards.service.MBThreadFlagLocalServiceUtil;
051    import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
052    import com.liferay.portlet.messageboards.service.persistence.MBBanUtil;
053    import com.liferay.portlet.messageboards.service.persistence.MBCategoryUtil;
054    import com.liferay.portlet.messageboards.service.persistence.MBMessageUtil;
055    import com.liferay.portlet.messageboards.service.persistence.MBThreadFlagUtil;
056    import com.liferay.portlet.messageboards.service.persistence.MBThreadUtil;
057    
058    import java.io.InputStream;
059    
060    import java.util.ArrayList;
061    import java.util.Collections;
062    import java.util.Iterator;
063    import java.util.List;
064    import java.util.Map;
065    
066    import javax.portlet.PortletPreferences;
067    
068    /**
069     * @author Bruno Farache
070     * @author Raymond Augé
071     */
072    public class MBPortletDataHandlerImpl extends BasePortletDataHandler {
073    
074            @Override
075            public PortletDataHandlerControl[] getExportControls() {
076                    return new PortletDataHandlerControl[] {
077                            _categoriesAndMessages, _attachments, _threadFlags, _userBans,
078                            _ratings, _tags
079                    };
080            }
081    
082            @Override
083            public PortletDataHandlerControl[] getImportControls() {
084                    return new PortletDataHandlerControl[] {
085                            _categoriesAndMessages, _attachments, _threadFlags, _userBans,
086                            _ratings, _tags
087                    };
088            }
089    
090            @Override
091            public boolean isAlwaysExportable() {
092                    return _ALWAYS_EXPORTABLE;
093            }
094    
095            @Override
096            public boolean isPublishToLiveByDefault() {
097                    return PropsValues.MESSAGE_BOARDS_PUBLISH_TO_LIVE_BY_DEFAULT;
098            }
099    
100            @Override
101            protected PortletPreferences doDeleteData(
102                            PortletDataContext portletDataContext, String portletId,
103                            PortletPreferences portletPreferences)
104                    throws Exception {
105    
106                    if (!portletDataContext.addPrimaryKey(
107                                    MBPortletDataHandlerImpl.class, "deleteData")) {
108    
109                            MBCategoryLocalServiceUtil.deleteCategories(
110                                    portletDataContext.getScopeGroupId());
111    
112                            MBThreadLocalServiceUtil.deleteThreads(
113                                    portletDataContext.getScopeGroupId(),
114                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);
115                    }
116    
117                    return null;
118            }
119    
120            @Override
121            protected String doExportData(
122                            PortletDataContext portletDataContext, String portletId,
123                            PortletPreferences portletPreferences)
124                    throws Exception {
125    
126                    portletDataContext.addPermissions(
127                            "com.liferay.portlet.messageboards",
128                            portletDataContext.getScopeGroupId());
129    
130                    Document document = SAXReaderUtil.createDocument();
131    
132                    Element rootElement = document.addElement("message-boards-data");
133    
134                    rootElement.addAttribute(
135                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
136    
137                    Element categoriesElement = rootElement.addElement("categories");
138                    Element messagesElement = rootElement.addElement("messages");
139                    Element threadFlagsElement = rootElement.addElement("thread-flags");
140                    Element userBansElement = rootElement.addElement("user-bans");
141    
142                    List<MBCategory> categories = MBCategoryUtil.findByGroupId(
143                            portletDataContext.getScopeGroupId());
144    
145                    for (MBCategory category : categories) {
146                            exportCategory(
147                                    portletDataContext, categoriesElement, messagesElement,
148                                    threadFlagsElement, category);
149                    }
150    
151                    List<MBMessage> messages = MBMessageUtil.findByG_C(
152                            portletDataContext.getScopeGroupId(),
153                            MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);
154    
155                    for (MBMessage message : messages) {
156                            exportMessage(
157                                    portletDataContext, categoriesElement, messagesElement,
158                                    threadFlagsElement, message);
159                    }
160    
161                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "user-bans")) {
162                            List<MBBan> bans = MBBanUtil.findByGroupId(
163                                    portletDataContext.getScopeGroupId());
164    
165                            for (MBBan ban : bans) {
166                                    exportBan(portletDataContext, userBansElement, ban);
167                            }
168                    }
169    
170                    return document.formattedString();
171            }
172    
173            @Override
174            protected PortletPreferences doImportData(
175                            PortletDataContext portletDataContext, String portletId,
176                            PortletPreferences portletPreferences, String data)
177                    throws Exception {
178    
179                    portletDataContext.importPermissions(
180                            "com.liferay.portlet.messageboards",
181                            portletDataContext.getSourceGroupId(),
182                            portletDataContext.getScopeGroupId());
183    
184                    Document document = SAXReaderUtil.read(data);
185    
186                    Element rootElement = document.getRootElement();
187    
188                    Element categoriesElement = rootElement.element("categories");
189    
190                    for (Element categoryElement : categoriesElement.elements("category")) {
191                            String path = categoryElement.attributeValue("path");
192    
193                            if (!portletDataContext.isPathNotProcessed(path)) {
194                                    continue;
195                            }
196    
197                            MBCategory category =
198                                    (MBCategory)portletDataContext.getZipEntryAsObject(path);
199    
200                            importCategory(portletDataContext, path, category);
201                    }
202    
203                    Element messagesElement = rootElement.element("messages");
204    
205                    for (Element messageElement : messagesElement.elements("message")) {
206                            String path = messageElement.attributeValue("path");
207    
208                            if (!portletDataContext.isPathNotProcessed(path)) {
209                                    continue;
210                            }
211    
212                            MBMessage message =
213                                    (MBMessage)portletDataContext.getZipEntryAsObject(path);
214    
215                            importMessage(portletDataContext, messageElement, message);
216                    }
217    
218                    if (portletDataContext.getBooleanParameter(
219                                    _NAMESPACE, "thread-flags")) {
220    
221                            Element threadFlagsElement = rootElement.element("thread-flags");
222    
223                            for (Element threadFlagElement :
224                                            threadFlagsElement.elements("thread-flag")) {
225    
226                                    String path = threadFlagElement.attributeValue("path");
227    
228                                    if (!portletDataContext.isPathNotProcessed(path)) {
229                                            continue;
230                                    }
231    
232                                    MBThreadFlag threadFlag =
233                                            (MBThreadFlag)portletDataContext.getZipEntryAsObject(path);
234    
235                                    importThreadFlag(
236                                            portletDataContext, threadFlagElement, threadFlag);
237                            }
238                    }
239    
240                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "user-bans")) {
241                            Element userBansElement = rootElement.element("user-bans");
242    
243                            for (Element userBanElement :
244                                            userBansElement.elements("user-ban")) {
245    
246                                    String path = userBanElement.attributeValue("path");
247    
248                                    if (!portletDataContext.isPathNotProcessed(path)) {
249                                            continue;
250                                    }
251    
252                                    MBBan ban = (MBBan)portletDataContext.getZipEntryAsObject(path);
253    
254                                    importBan(portletDataContext, userBanElement, ban);
255                            }
256                    }
257    
258                    return null;
259            }
260    
261            protected void exportBan(
262                            PortletDataContext portletDataContext, Element userBansElement,
263                            MBBan ban)
264                    throws Exception {
265    
266                    if (!portletDataContext.isWithinDateRange(ban.getModifiedDate())) {
267                            return;
268                    }
269    
270                    String path = getUserBanPath(portletDataContext, ban);
271    
272                    if (!portletDataContext.isPathNotProcessed(path)) {
273                            return;
274                    }
275    
276                    Element userBanElement = userBansElement.addElement("user-ban");
277    
278                    ban.setBanUserUuid(ban.getBanUserUuid());
279    
280                    portletDataContext.addClassedModel(
281                            userBanElement, path, ban, _NAMESPACE);
282            }
283    
284            protected void exportCategory(
285                            PortletDataContext portletDataContext, Element categoriesElement,
286                            Element messagesElement, Element threadFlagsElement,
287                            MBCategory category)
288                    throws Exception {
289    
290                    if (portletDataContext.isWithinDateRange(category.getModifiedDate())) {
291                            exportParentCategory(
292                                    portletDataContext, categoriesElement,
293                                    category.getParentCategoryId());
294    
295                            String path = getCategoryPath(portletDataContext, category);
296    
297                            if (portletDataContext.isPathNotProcessed(path)) {
298                                    Element categoryElement = categoriesElement.addElement(
299                                            "category");
300    
301                                    portletDataContext.addClassedModel(
302                                            categoryElement, path, category, _NAMESPACE);
303                            }
304                    }
305    
306                    List<MBMessage> messages = MBMessageUtil.findByG_C(
307                            category.getGroupId(), category.getCategoryId());
308    
309                    for (MBMessage message : messages) {
310                            exportMessage(
311                                    portletDataContext, categoriesElement, messagesElement,
312                                    threadFlagsElement, message);
313                    }
314            }
315    
316            protected void exportMessage(
317                            PortletDataContext portletDataContext, Element categoriesElement,
318                            Element messagesElement, Element threadFlagsElement,
319                            MBMessage message)
320                    throws Exception {
321    
322                    if (!portletDataContext.isWithinDateRange(message.getModifiedDate())) {
323                            return;
324                    }
325    
326                    if (message.getStatus() != WorkflowConstants.STATUS_APPROVED) {
327                            return;
328                    }
329    
330                    exportParentCategory(
331                            portletDataContext, categoriesElement, message.getCategoryId());
332    
333                    String path = getMessagePath(portletDataContext, message);
334    
335                    if (!portletDataContext.isPathNotProcessed(path)) {
336                            return;
337                    }
338    
339                    Element messageElement = messagesElement.addElement("message");
340    
341                    message.setPriority(message.getPriority());
342    
343                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "attachments") &&
344                            message.isAttachments()) {
345    
346                            for (String attachment : message.getAttachmentsFiles()) {
347                                    int pos = attachment.lastIndexOf(CharPool.FORWARD_SLASH);
348    
349                                    String name = attachment.substring(pos + 1);
350                                    String binPath = getMessageAttachementBinPath(
351                                            portletDataContext, message, name);
352    
353                                    Element attachmentElement = messageElement.addElement(
354                                            "attachment");
355    
356                                    attachmentElement.addAttribute("name", name);
357                                    attachmentElement.addAttribute("bin-path", binPath);
358    
359                                    byte[] bytes = DLStoreUtil.getFileAsBytes(
360                                            portletDataContext.getCompanyId(), CompanyConstants.SYSTEM,
361                                            attachment);
362    
363                                    portletDataContext.addZipEntry(binPath, bytes);
364                            }
365    
366                            message.setAttachmentsDir(message.getAttachmentsDir());
367                    }
368    
369                    if (portletDataContext.getBooleanParameter(
370                                    _NAMESPACE, "thread-flags")) {
371    
372                            List<MBThreadFlag> threadFlags = MBThreadFlagUtil.findByThreadId(
373                                    message.getThreadId());
374    
375                            for (MBThreadFlag threadFlag : threadFlags) {
376                                    exportThreadFlag(
377                                            portletDataContext, threadFlagsElement, threadFlag);
378                            }
379                    }
380    
381                    portletDataContext.addClassedModel(
382                            messageElement, path, message, _NAMESPACE);
383            }
384    
385            protected void exportParentCategory(
386                            PortletDataContext portletDataContext, Element categoriesElement,
387                            long categoryId)
388                    throws Exception {
389    
390                    if ((!portletDataContext.hasDateRange()) ||
391                            (categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) ||
392                            (categoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
393    
394                            return;
395                    }
396    
397                    MBCategory category = MBCategoryUtil.findByPrimaryKey(categoryId);
398    
399                    exportParentCategory(
400                            portletDataContext, categoriesElement,
401                            category.getParentCategoryId());
402    
403                    String path = getCategoryPath(portletDataContext, category);
404    
405                    if (portletDataContext.isPathNotProcessed(path)) {
406                            Element categoryElement = categoriesElement.addElement("category");
407    
408                            portletDataContext.addClassedModel(
409                                    categoryElement, path, category, _NAMESPACE);
410                    }
411            }
412    
413            protected void exportThreadFlag(
414                            PortletDataContext portletDataContext, Element threadFlagsElement,
415                            MBThreadFlag threadFlag)
416                    throws Exception {
417    
418                    String path = getThreadFlagPath(portletDataContext, threadFlag);
419    
420                    if (!portletDataContext.isPathNotProcessed(path)) {
421                            return;
422                    }
423    
424                    Element threadFlagElement = threadFlagsElement.addElement(
425                            "thread-flag");
426    
427                    MBThread thread = MBThreadLocalServiceUtil.getThread(
428                            threadFlag.getThreadId());
429    
430                    MBMessage rootMessage = MBMessageLocalServiceUtil.getMessage(
431                            thread.getRootMessageId());
432    
433                    threadFlagElement.addAttribute(
434                            "root-message-uuid", rootMessage.getUuid());
435    
436                    portletDataContext.addClassedModel(
437                            threadFlagElement, path, threadFlag, _NAMESPACE);
438            }
439    
440            protected List<ObjectValuePair<String, InputStream>> getAttachments(
441                    PortletDataContext portletDataContext, Element messageElement,
442                    MBMessage message) {
443    
444                    if (!message.isAttachments() &&
445                            portletDataContext.getBooleanParameter(_NAMESPACE, "attachments")) {
446    
447                            return Collections.emptyList();
448                    }
449    
450                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
451                            new ArrayList<ObjectValuePair<String, InputStream>>();
452    
453                    List<Element> attachmentElements = messageElement.elements(
454                            "attachment");
455    
456                    for (Element attachmentElement : attachmentElements) {
457                            String name = attachmentElement.attributeValue("name");
458                            String binPath = attachmentElement.attributeValue("bin-path");
459    
460                            InputStream inputStream =
461                                    portletDataContext.getZipEntryAsInputStream(binPath);
462    
463                            ObjectValuePair<String, InputStream> inputStreamOVP =
464                                    new ObjectValuePair<String, InputStream>(name, inputStream);
465    
466                            inputStreamOVPs.add(inputStreamOVP);
467                    }
468    
469                    if (inputStreamOVPs.isEmpty()) {
470                            _log.error(
471                                    "Could not find attachments for message " +
472                                            message.getMessageId());
473                    }
474    
475                    return inputStreamOVPs;
476            }
477    
478            protected long getCategoryId(
479                            PortletDataContext portletDataContext, MBMessage message,
480                            Map<Long, Long> categoryPKs, long categoryId)
481                    throws Exception {
482    
483                    if ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
484                            (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID) &&
485                            (categoryId == message.getCategoryId())) {
486    
487                            String path = getImportCategoryPath(portletDataContext, categoryId);
488    
489                            MBCategory category =
490                                    (MBCategory)portletDataContext.getZipEntryAsObject(path);
491    
492                            importCategory(portletDataContext, path, category);
493    
494                            categoryId = MapUtil.getLong(
495                                    categoryPKs, message.getCategoryId(), message.getCategoryId());
496                    }
497    
498                    return categoryId;
499            }
500    
501            protected String getCategoryPath(
502                    PortletDataContext portletDataContext, MBCategory category) {
503    
504                    StringBundler sb = new StringBundler(4);
505    
506                    sb.append(
507                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
508                    sb.append("/categories/");
509                    sb.append(category.getCategoryId());
510                    sb.append(".xml");
511    
512                    return sb.toString();
513            }
514    
515            protected String getImportCategoryPath(
516                    PortletDataContext portletDataContext, long categoryId) {
517    
518                    StringBundler sb = new StringBundler(4);
519    
520                    sb.append(
521                            portletDataContext.getSourcePortletPath(
522                                    PortletKeys.MESSAGE_BOARDS));
523                    sb.append("/categories/");
524                    sb.append(categoryId);
525                    sb.append(".xml");
526    
527                    return sb.toString();
528            }
529    
530            protected String getMessageAttachementBinPath(
531                    PortletDataContext portletDataContext, MBMessage message,
532                    String attachment) {
533    
534                    StringBundler sb = new StringBundler(5);
535    
536                    sb.append(
537                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
538                    sb.append("/bin/");
539                    sb.append(message.getMessageId());
540                    sb.append(StringPool.SLASH);
541                    sb.append(PortalUUIDUtil.generate());
542    
543                    return sb.toString();
544            }
545    
546            protected String getMessagePath(
547                    PortletDataContext portletDataContext, MBMessage message) {
548    
549                    StringBundler sb = new StringBundler(4);
550    
551                    sb.append(
552                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
553                    sb.append("/messages/");
554                    sb.append(message.getMessageId());
555                    sb.append(".xml");
556    
557                    return sb.toString();
558            }
559    
560            protected String getThreadFlagPath(
561                    PortletDataContext portletDataContext, MBThreadFlag threadFlag) {
562    
563                    StringBundler sb = new StringBundler(4);
564    
565                    sb.append(
566                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
567                    sb.append("/thread-flags/");
568                    sb.append(threadFlag.getThreadFlagId());
569                    sb.append(".xml");
570    
571                    return sb.toString();
572            }
573    
574            protected String getUserBanPath(
575                    PortletDataContext portletDataContext, MBBan ban) {
576    
577                    StringBundler sb = new StringBundler(4);
578    
579                    sb.append(
580                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
581                    sb.append("/user-bans/");
582                    sb.append(ban.getBanId());
583                    sb.append(".xml");
584    
585                    return sb.toString();
586            }
587    
588            protected void importBan(
589                            PortletDataContext portletDataContext, Element userBanElement,
590                            MBBan ban)
591                    throws Exception {
592    
593                    long userId = portletDataContext.getUserId(ban.getUserUuid());
594    
595                    ServiceContext serviceContext = portletDataContext.createServiceContext(
596                            userBanElement, ban, _NAMESPACE);
597    
598                    List<User> users = UserUtil.findByUuid(ban.getBanUserUuid());
599    
600                    Iterator<User> itr = users.iterator();
601    
602                    if (itr.hasNext()) {
603                            User user = itr.next();
604    
605                            MBBanLocalServiceUtil.addBan(
606                                    userId, user.getUserId(), serviceContext);
607                    }
608                    else {
609                            _log.error(
610                                    "Could not find banned user with uuid " + ban.getBanUserUuid());
611                    }
612            }
613    
614            protected void importCategory(
615                            PortletDataContext portletDataContext, String categoryPath,
616                            MBCategory category)
617                    throws Exception {
618    
619                    long userId = portletDataContext.getUserId(category.getUserUuid());
620    
621                    Map<Long, Long> categoryPKs =
622                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
623                                    MBCategory.class);
624    
625                    long parentCategoryId = MapUtil.getLong(
626                            categoryPKs, category.getParentCategoryId(),
627                            category.getParentCategoryId());
628    
629                    String emailAddress = null;
630                    String inProtocol = null;
631                    String inServerName = null;
632                    int inServerPort = 0;
633                    boolean inUseSSL = false;
634                    String inUserName = null;
635                    String inPassword = null;
636                    int inReadInterval = 0;
637                    String outEmailAddress = null;
638                    boolean outCustom = false;
639                    String outServerName = null;
640                    int outServerPort = 0;
641                    boolean outUseSSL = false;
642                    String outUserName = null;
643                    String outPassword = null;
644                    boolean allowAnonymous = false;
645                    boolean mailingListActive = false;
646    
647                    ServiceContext serviceContext = portletDataContext.createServiceContext(
648                            categoryPath, category, _NAMESPACE);
649    
650                    if ((parentCategoryId !=
651                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
652                            (parentCategoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID) &&
653                            (parentCategoryId == category.getParentCategoryId())) {
654    
655                            String path = getImportCategoryPath(
656                                    portletDataContext, parentCategoryId);
657    
658                            MBCategory parentCategory =
659                                    (MBCategory)portletDataContext.getZipEntryAsObject(path);
660    
661                            importCategory(portletDataContext, path, parentCategory);
662    
663                            parentCategoryId = MapUtil.getLong(
664                                    categoryPKs, category.getParentCategoryId(),
665                                    category.getParentCategoryId());
666                    }
667    
668                    MBCategory importedCategory = null;
669    
670                    if (portletDataContext.isDataStrategyMirror()) {
671                            MBCategory existingCategory = MBCategoryUtil.fetchByUUID_G(
672                                    category.getUuid(), portletDataContext.getScopeGroupId());
673    
674                            if (existingCategory == null) {
675                                    serviceContext.setUuid(category.getUuid());
676    
677                                    importedCategory = MBCategoryLocalServiceUtil.addCategory(
678                                            userId, parentCategoryId, category.getName(),
679                                            category.getDescription(), category.getDisplayStyle(),
680                                            emailAddress, inProtocol, inServerName, inServerPort,
681                                            inUseSSL, inUserName, inPassword, inReadInterval,
682                                            outEmailAddress, outCustom, outServerName, outServerPort,
683                                            outUseSSL, outUserName, outPassword, allowAnonymous,
684                                            mailingListActive, serviceContext);
685                            }
686                            else {
687                                    importedCategory = MBCategoryLocalServiceUtil.updateCategory(
688                                            existingCategory.getCategoryId(), parentCategoryId,
689                                            category.getName(), category.getDescription(),
690                                            category.getDisplayStyle(), emailAddress, inProtocol,
691                                            inServerName, inServerPort, inUseSSL, inUserName,
692                                            inPassword, inReadInterval, outEmailAddress, outCustom,
693                                            outServerName, outServerPort, outUseSSL, outUserName,
694                                            outPassword, allowAnonymous, mailingListActive, false,
695                                            serviceContext);
696                            }
697                    }
698                    else {
699                            importedCategory = MBCategoryLocalServiceUtil.addCategory(
700                                    userId, parentCategoryId, category.getName(),
701                                    category.getDescription(), category.getDisplayStyle(),
702                                    emailAddress, inProtocol, inServerName, inServerPort, inUseSSL,
703                                    inUserName, inPassword, inReadInterval, outEmailAddress,
704                                    outCustom, outServerName, outServerPort, outUseSSL, outUserName,
705                                    outPassword, allowAnonymous, mailingListActive, serviceContext);
706                    }
707    
708                    portletDataContext.importClassedModel(
709                            category, importedCategory, _NAMESPACE);
710            }
711    
712            protected void importMessage(
713                            PortletDataContext portletDataContext, Element messageElement,
714                            MBMessage message)
715                    throws Exception {
716    
717                    long userId = portletDataContext.getUserId(message.getUserUuid());
718                    String userName = message.getUserName();
719    
720                    Map<Long, Long> categoryPKs =
721                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
722                                    MBCategory.class);
723    
724                    long categoryId = MapUtil.getLong(
725                            categoryPKs, message.getCategoryId(), message.getCategoryId());
726    
727                    Map<Long, Long> threadPKs =
728                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
729                                    MBThread.class);
730    
731                    long threadId = MapUtil.getLong(threadPKs, message.getThreadId(), 0);
732    
733                    Map<Long, Long> messagePKs =
734                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
735                                    MBMessage.class);
736    
737                    long parentMessageId = MapUtil.getLong(
738                            messagePKs, message.getParentMessageId(),
739                            message.getParentMessageId());
740    
741                    List<String> existingFiles = new ArrayList<String>();
742    
743                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
744                            getAttachments(portletDataContext, messageElement, message);
745    
746                    try {
747                            ServiceContext serviceContext =
748                                    portletDataContext.createServiceContext(
749                                            messageElement, message, _NAMESPACE);
750    
751                            if (message.getStatus() != WorkflowConstants.STATUS_APPROVED) {
752                                    serviceContext.setWorkflowAction(
753                                            WorkflowConstants.ACTION_SAVE_DRAFT);
754                            }
755    
756                            categoryId = getCategoryId(
757                                    portletDataContext, message, categoryPKs, categoryId);
758    
759                            MBMessage importedMessage = null;
760    
761                            if (portletDataContext.isDataStrategyMirror()) {
762                                    MBMessage existingMessage = MBMessageUtil.fetchByUUID_G(
763                                            message.getUuid(), portletDataContext.getScopeGroupId());
764    
765                                    if (existingMessage == null) {
766                                            serviceContext.setUuid(message.getUuid());
767    
768                                            importedMessage = MBMessageLocalServiceUtil.addMessage(
769                                                    userId, userName, portletDataContext.getScopeGroupId(),
770                                                    categoryId, threadId, parentMessageId,
771                                                    message.getSubject(), message.getBody(),
772                                                    message.getFormat(), inputStreamOVPs,
773                                                    message.getAnonymous(), message.getPriority(),
774                                                    message.getAllowPingbacks(), serviceContext);
775                                    }
776                                    else {
777                                            importedMessage = MBMessageLocalServiceUtil.updateMessage(
778                                                    userId, existingMessage.getMessageId(),
779                                                    message.getSubject(), message.getBody(),
780                                                    inputStreamOVPs, existingFiles, message.getPriority(),
781                                                    message.getAllowPingbacks(), serviceContext);
782                                    }
783                            }
784                            else {
785                                    importedMessage = MBMessageLocalServiceUtil.addMessage(
786                                            userId, userName, portletDataContext.getScopeGroupId(),
787                                            categoryId, threadId, parentMessageId, message.getSubject(),
788                                            message.getBody(), message.getFormat(), inputStreamOVPs,
789                                            message.getAnonymous(), message.getPriority(),
790                                            message.getAllowPingbacks(), serviceContext);
791                            }
792    
793                            threadPKs.put(message.getThreadId(), importedMessage.getThreadId());
794    
795                            portletDataContext.importClassedModel(
796                                    message, importedMessage, _NAMESPACE);
797                    }
798                    finally {
799                            for (ObjectValuePair<String, InputStream> inputStreamOVP :
800                                            inputStreamOVPs) {
801    
802                                    InputStream inputStream = inputStreamOVP.getValue();
803    
804                                    StreamUtil.cleanUp(inputStream);
805                            }
806                    }
807            }
808    
809            protected void importThreadFlag(
810                            PortletDataContext portletDataContext, Element threadFlagElement,
811                            MBThreadFlag threadFlag)
812                    throws Exception {
813    
814                    long userId = portletDataContext.getUserId(threadFlag.getUserUuid());
815    
816                    Map<Long, Long> messagePKs =
817                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
818                                    MBMessage.class);
819    
820                    long threadId = MapUtil.getLong(
821                            messagePKs, threadFlag.getThreadId(), threadFlag.getThreadId());
822    
823                    MBThread thread = MBThreadUtil.fetchByPrimaryKey(threadId);
824    
825                    if (thread == null) {
826                            String rootMessageUuid = threadFlagElement.attributeValue(
827                                    "root-message-uuid");
828    
829                            MBMessage rootMessage = MBMessageUtil.fetchByUUID_G(
830                                    rootMessageUuid, portletDataContext.getScopeGroupId());
831    
832                            if (rootMessage != null) {
833                                    thread = rootMessage.getThread();
834                            }
835                    }
836    
837                    if (thread == null) {
838                            return;
839                    }
840    
841                    MBThreadFlagLocalServiceUtil.addThreadFlag(userId, thread);
842            }
843    
844            private static final boolean _ALWAYS_EXPORTABLE = true;
845    
846            private static final String _NAMESPACE = "message_board";
847    
848            private static Log _log = LogFactoryUtil.getLog(
849                    MBPortletDataHandlerImpl.class);
850    
851            private static PortletDataHandlerBoolean _attachments =
852                    new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
853    
854            private static PortletDataHandlerBoolean _categoriesAndMessages =
855                    new PortletDataHandlerBoolean(
856                            _NAMESPACE, "categories-and-messages", true, true);
857    
858            private static PortletDataHandlerBoolean _ratings =
859                    new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
860    
861            private static PortletDataHandlerBoolean _tags =
862                    new PortletDataHandlerBoolean(_NAMESPACE, "tags");
863    
864            private static PortletDataHandlerBoolean _threadFlags =
865                    new PortletDataHandlerBoolean(_NAMESPACE, "thread-flags");
866    
867            private static PortletDataHandlerBoolean _userBans =
868                    new PortletDataHandlerBoolean(_NAMESPACE, "user-bans");
869    
870    }