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