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