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.BaseStagedModelDataHandler;
018    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
019    import com.liferay.portal.kernel.lar.PortletDataContext;
020    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
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.workflow.WorkflowConstants;
029    import com.liferay.portal.kernel.xml.Element;
030    import com.liferay.portal.service.ServiceContext;
031    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
032    import com.liferay.portlet.messageboards.model.MBCategory;
033    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
034    import com.liferay.portlet.messageboards.model.MBMessage;
035    import com.liferay.portlet.messageboards.model.MBThread;
036    import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
037    import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
038    import com.liferay.portlet.messageboards.service.persistence.MBMessageUtil;
039    
040    import java.io.InputStream;
041    
042    import java.util.ArrayList;
043    import java.util.Collections;
044    import java.util.List;
045    import java.util.Map;
046    
047    /**
048     * @author Daniel Kocsis
049     */
050    public class MBMessageStagedModelDataHandler
051            extends BaseStagedModelDataHandler<MBMessage> {
052    
053            public static final String[] CLASS_NAMES = {MBMessage.class.getName()};
054    
055            @Override
056            public String[] getClassNames() {
057                    return CLASS_NAMES;
058            }
059    
060            @Override
061            protected void doExportStagedModel(
062                            PortletDataContext portletDataContext, MBMessage message)
063                    throws Exception {
064    
065                    if ((message.getStatus() != WorkflowConstants.STATUS_APPROVED) ||
066                            (message.getCategoryId() ==
067                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
068    
069                            return;
070                    }
071    
072                    StagedModelDataHandlerUtil.exportStagedModel(
073                            portletDataContext, message.getCategory());
074    
075                    Element messageElement =
076                            portletDataContext.getExportDataStagedModelElement(message);
077    
078                    message.setPriority(message.getPriority());
079    
080                    MBThread thread = message.getThread();
081    
082                    messageElement.addAttribute(
083                            "question", String.valueOf(thread.isQuestion()));
084    
085                    boolean hasAttachmentsFileEntries =
086                            message.getAttachmentsFileEntriesCount() > 0;
087    
088                    messageElement.addAttribute(
089                            "hasAttachmentsFileEntries",
090                            String.valueOf(hasAttachmentsFileEntries));
091    
092                    if (portletDataContext.getBooleanParameter(
093                                    MBPortletDataHandler.NAMESPACE, "attachments") &&
094                            hasAttachmentsFileEntries) {
095    
096                            for (FileEntry fileEntry : message.getAttachmentsFileEntries()) {
097                                    String name = fileEntry.getTitle();
098                                    String binPath = ExportImportPathUtil.getModelPath(
099                                            message, name);
100    
101                                    Element attachmentElement = messageElement.addElement(
102                                            "attachment");
103    
104                                    attachmentElement.addAttribute("name", name);
105                                    attachmentElement.addAttribute("bin-path", binPath);
106    
107                                    portletDataContext.addZipEntry(
108                                            binPath, fileEntry.getContentStream());
109                            }
110    
111                            long folderId = message.getAttachmentsFolderId();
112    
113                            if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
114                                    message.setAttachmentsFolderId(folderId);
115                            }
116                    }
117    
118                    portletDataContext.addClassedModel(
119                            messageElement, ExportImportPathUtil.getModelPath(message), message,
120                            MBPortletDataHandler.NAMESPACE);
121            }
122    
123            @Override
124            protected void doImportStagedModel(
125                            PortletDataContext portletDataContext, MBMessage message)
126                    throws Exception {
127    
128                    long userId = portletDataContext.getUserId(message.getUserUuid());
129    
130                    String userName = message.getUserName();
131    
132                    Map<Long, Long> categoryIds =
133                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
134                                    MBCategory.class);
135    
136                    long parentCategoryId = MapUtil.getLong(
137                            categoryIds, message.getCategoryId(), message.getCategoryId());
138    
139                    Map<Long, Long> threadIds =
140                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
141                                    MBThread.class);
142    
143                    long threadId = MapUtil.getLong(threadIds, message.getThreadId(), 0);
144    
145                    Map<Long, Long> messageIds =
146                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
147                                    MBMessage.class);
148    
149                    long parentMessageId = MapUtil.getLong(
150                            messageIds, message.getParentMessageId(),
151                            message.getParentMessageId());
152    
153                    Element element = portletDataContext.getImportDataStagedModelElement(
154                            message);
155    
156                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
157                            getAttachments(portletDataContext, element, message);
158    
159                    try {
160                            ServiceContext serviceContext =
161                                    portletDataContext.createServiceContext(
162                                            message, MBPortletDataHandler.NAMESPACE);
163    
164                            if (message.getStatus() != WorkflowConstants.STATUS_APPROVED) {
165                                    serviceContext.setWorkflowAction(
166                                            WorkflowConstants.ACTION_SAVE_DRAFT);
167                            }
168    
169                            if ((parentCategoryId !=
170                                            MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
171                                    (parentCategoryId !=
172                                            MBCategoryConstants.DISCUSSION_CATEGORY_ID) &&
173                                    (parentCategoryId == message.getCategoryId())) {
174    
175                                    String categoryPath = ExportImportPathUtil.getModelPath(
176                                            portletDataContext, MBCategory.class.getName(),
177                                            parentCategoryId);
178    
179                                    MBCategory category =
180                                            (MBCategory)portletDataContext.getZipEntryAsObject(
181                                                    categoryPath);
182    
183                                    StagedModelDataHandlerUtil.importStagedModel(
184                                            portletDataContext, category);
185    
186                                    parentCategoryId = MapUtil.getLong(
187                                            categoryIds, message.getCategoryId(),
188                                            message.getCategoryId());
189                            }
190    
191                            MBMessage importedMessage = null;
192    
193                            if (portletDataContext.isDataStrategyMirror()) {
194                                    MBMessage existingMessage = MBMessageUtil.fetchByUUID_G(
195                                            message.getUuid(), portletDataContext.getScopeGroupId());
196    
197                                    if (existingMessage == null) {
198                                            serviceContext.setUuid(message.getUuid());
199    
200                                            importedMessage = MBMessageLocalServiceUtil.addMessage(
201                                                    userId, userName, portletDataContext.getScopeGroupId(),
202                                                    parentCategoryId, threadId, parentMessageId,
203                                                    message.getSubject(), message.getBody(),
204                                                    message.getFormat(), inputStreamOVPs,
205                                                    message.getAnonymous(), message.getPriority(),
206                                                    message.getAllowPingbacks(), serviceContext);
207                                    }
208                                    else {
209                                            importedMessage = MBMessageLocalServiceUtil.updateMessage(
210                                                    userId, existingMessage.getMessageId(),
211                                                    message.getSubject(), message.getBody(),
212                                                    inputStreamOVPs, new ArrayList<String>(),
213                                                    message.getPriority(), message.getAllowPingbacks(),
214                                                    serviceContext);
215                                    }
216                            }
217                            else {
218                                    importedMessage = MBMessageLocalServiceUtil.addMessage(
219                                            userId, userName, portletDataContext.getScopeGroupId(),
220                                            parentCategoryId, threadId, parentMessageId,
221                                            message.getSubject(), message.getBody(),
222                                            message.getFormat(), inputStreamOVPs,
223                                            message.getAnonymous(), message.getPriority(),
224                                            message.getAllowPingbacks(), serviceContext);
225                            }
226    
227                            importedMessage.setAnswer(message.getAnswer());
228    
229                            if (importedMessage.isRoot()) {
230                                    MBThreadLocalServiceUtil.updateQuestion(
231                                            importedMessage.getThreadId(),
232                                            GetterUtil.getBoolean(element.attributeValue("question")));
233                            }
234    
235                            threadIds.put(message.getThreadId(), importedMessage.getThreadId());
236    
237                            portletDataContext.importClassedModel(
238                                    message, importedMessage, MBPortletDataHandler.NAMESPACE);
239                    }
240                    finally {
241                            for (ObjectValuePair<String, InputStream> inputStreamOVP :
242                                            inputStreamOVPs) {
243    
244                                    InputStream inputStream = inputStreamOVP.getValue();
245    
246                                    StreamUtil.cleanUp(inputStream);
247                            }
248                    }
249            }
250    
251            protected List<ObjectValuePair<String, InputStream>> getAttachments(
252                    PortletDataContext portletDataContext, Element messageElement,
253                    MBMessage message) {
254    
255                    boolean hasAttachmentsFileEntries = GetterUtil.getBoolean(
256                            messageElement.attributeValue("hasAttachmentsFileEntries"));
257    
258                    if (!hasAttachmentsFileEntries &&
259                            portletDataContext.getBooleanParameter(
260                                    MBPortletDataHandler.NAMESPACE, "attachments")) {
261    
262                            return Collections.emptyList();
263                    }
264    
265                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
266                            new ArrayList<ObjectValuePair<String, InputStream>>();
267    
268                    List<Element> attachmentElements = messageElement.elements(
269                            "attachment");
270    
271                    for (Element attachmentElement : attachmentElements) {
272                            String name = attachmentElement.attributeValue("name");
273                            String binPath = attachmentElement.attributeValue("bin-path");
274    
275                            InputStream inputStream =
276                                    portletDataContext.getZipEntryAsInputStream(binPath);
277    
278                            if (inputStream == null) {
279                                    continue;
280                            }
281    
282                            ObjectValuePair<String, InputStream> inputStreamOVP =
283                                    new ObjectValuePair<String, InputStream>(name, inputStream);
284    
285                            inputStreamOVPs.add(inputStreamOVP);
286                    }
287    
288                    if (inputStreamOVPs.isEmpty()) {
289                            _log.error(
290                                    "Could not find attachments for message " +
291                                            message.getMessageId());
292                    }
293    
294                    return inputStreamOVPs;
295            }
296    
297            private static Log _log = LogFactoryUtil.getLog(
298                    MBMessageStagedModelDataHandler.class);
299    
300    }