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