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.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.lar.BaseStagedModelDataHandler;
020    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
021    import com.liferay.portal.kernel.lar.PortletDataContext;
022    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.repository.model.FileEntry;
026    import com.liferay.portal.kernel.trash.TrashHandler;
027    import com.liferay.portal.kernel.util.GetterUtil;
028    import com.liferay.portal.kernel.util.MapUtil;
029    import com.liferay.portal.kernel.util.ObjectValuePair;
030    import com.liferay.portal.kernel.util.StreamUtil;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.kernel.xml.Element;
033    import com.liferay.portal.service.ServiceContext;
034    import com.liferay.portlet.documentlibrary.lar.FileEntryUtil;
035    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
036    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
037    import com.liferay.portlet.messageboards.model.MBCategory;
038    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
039    import com.liferay.portlet.messageboards.model.MBMessage;
040    import com.liferay.portlet.messageboards.model.MBThread;
041    import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
042    import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
043    
044    import java.io.InputStream;
045    
046    import java.util.ArrayList;
047    import java.util.Collections;
048    import java.util.List;
049    import java.util.Map;
050    
051    /**
052     * @author Daniel Kocsis
053     */
054    public class MBMessageStagedModelDataHandler
055            extends BaseStagedModelDataHandler<MBMessage> {
056    
057            public static final String[] CLASS_NAMES = {MBMessage.class.getName()};
058    
059            @Override
060            public void deleteStagedModel(
061                            String uuid, long groupId, String className, String extraData)
062                    throws PortalException, SystemException {
063    
064                    MBMessage message =
065                            MBMessageLocalServiceUtil.fetchMBMessageByUuidAndGroupId(
066                                    uuid, groupId);
067    
068                    if (message != null) {
069                            MBMessageLocalServiceUtil.deleteMessage(message);
070                    }
071            }
072    
073            @Override
074            public String[] getClassNames() {
075                    return CLASS_NAMES;
076            }
077    
078            @Override
079            public String getDisplayName(MBMessage message) {
080                    return message.getSubject();
081            }
082    
083            @Override
084            protected void doExportStagedModel(
085                            PortletDataContext portletDataContext, MBMessage message)
086                    throws Exception {
087    
088                    if (message.getCategoryId() ==
089                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID) {
090    
091                            return;
092                    }
093    
094                    StagedModelDataHandlerUtil.exportReferenceStagedModel(
095                            portletDataContext, message, message.getCategory(),
096                            PortletDataContext.REFERENCE_TYPE_PARENT);
097    
098                    Element messageElement = portletDataContext.getExportDataElement(
099                            message);
100    
101                    message.setPriority(message.getPriority());
102    
103                    MBThread thread = message.getThread();
104    
105                    messageElement.addAttribute(
106                            "question", String.valueOf(thread.isQuestion()));
107    
108                    boolean hasAttachmentsFileEntries =
109                            message.getAttachmentsFileEntriesCount() > 0;
110    
111                    messageElement.addAttribute(
112                            "hasAttachmentsFileEntries",
113                            String.valueOf(hasAttachmentsFileEntries));
114    
115                    if (hasAttachmentsFileEntries) {
116                            for (FileEntry fileEntry : message.getAttachmentsFileEntries()) {
117                                    StagedModelDataHandlerUtil.exportReferenceStagedModel(
118                                            portletDataContext, message, fileEntry,
119                                            PortletDataContext.REFERENCE_TYPE_WEAK);
120                            }
121    
122                            long folderId = message.getAttachmentsFolderId();
123    
124                            if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
125                                    message.setAttachmentsFolderId(folderId);
126                            }
127                    }
128    
129                    portletDataContext.addClassedModel(
130                            messageElement, ExportImportPathUtil.getModelPath(message),
131                            message);
132            }
133    
134            @Override
135            protected void doImportStagedModel(
136                            PortletDataContext portletDataContext, MBMessage message)
137                    throws Exception {
138    
139                    long userId = portletDataContext.getUserId(message.getUserUuid());
140    
141                    String userName = message.getUserName();
142    
143                    Map<Long, Long> categoryIds =
144                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
145                                    MBCategory.class);
146    
147                    long parentCategoryId = MapUtil.getLong(
148                            categoryIds, message.getCategoryId(), message.getCategoryId());
149    
150                    Map<Long, Long> threadIds =
151                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
152                                    MBThread.class);
153    
154                    long threadId = MapUtil.getLong(threadIds, message.getThreadId(), 0);
155    
156                    Map<Long, Long> messageIds =
157                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
158                                    MBMessage.class);
159    
160                    long parentMessageId = MapUtil.getLong(
161                            messageIds, message.getParentMessageId(),
162                            message.getParentMessageId());
163    
164                    Element element = portletDataContext.getImportDataStagedModelElement(
165                            message);
166    
167                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
168                            getAttachments(portletDataContext, element, message);
169    
170                    try {
171                            ServiceContext serviceContext =
172                                    portletDataContext.createServiceContext(message);
173    
174                            if ((parentCategoryId !=
175                                            MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
176                                    (parentCategoryId !=
177                                            MBCategoryConstants.DISCUSSION_CATEGORY_ID) &&
178                                    (parentCategoryId == message.getCategoryId())) {
179    
180                                    StagedModelDataHandlerUtil.importReferenceStagedModel(
181                                            portletDataContext, message, MBCategory.class,
182                                            parentCategoryId);
183    
184                                    parentCategoryId = MapUtil.getLong(
185                                            categoryIds, message.getCategoryId(),
186                                            message.getCategoryId());
187                            }
188    
189                            MBMessage importedMessage = null;
190    
191                            if (portletDataContext.isDataStrategyMirror()) {
192                                    MBMessage existingMessage =
193                                            MBMessageLocalServiceUtil.fetchMBMessageByUuidAndGroupId(
194                                                    message.getUuid(),
195                                                    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(message, importedMessage);
238                    }
239                    finally {
240                            for (ObjectValuePair<String, InputStream> inputStreamOVP :
241                                            inputStreamOVPs) {
242    
243                                    InputStream inputStream = inputStreamOVP.getValue();
244    
245                                    StreamUtil.cleanUp(inputStream);
246                            }
247                    }
248            }
249    
250            @Override
251            protected void doRestoreStagedModel(
252                            PortletDataContext portletDataContext, MBMessage message)
253                    throws Exception {
254    
255                    long userId = portletDataContext.getUserId(message.getUserUuid());
256    
257                    MBMessage existingMessage =
258                            MBMessageLocalServiceUtil.fetchMBMessageByUuidAndGroupId(
259                                    message.getUuid(), portletDataContext.getScopeGroupId());
260    
261                    if (existingMessage == null) {
262                            return;
263                    }
264    
265                    if (existingMessage.isInTrash()) {
266                            TrashHandler trashHandler = existingMessage.getTrashHandler();
267    
268                            if (trashHandler.isRestorable(existingMessage.getMessageId())) {
269                                    trashHandler.restoreTrashEntry(
270                                            userId, existingMessage.getMessageId());
271                            }
272                    }
273    
274                    if (existingMessage.isInTrashContainer()) {
275                            MBThread existingThread = existingMessage.getThread();
276    
277                            TrashHandler trashHandler = existingThread.getTrashHandler();
278    
279                            if (trashHandler.isRestorable(existingThread.getThreadId())) {
280                                    trashHandler.restoreTrashEntry(
281                                            userId, existingThread.getThreadId());
282                            }
283                    }
284            }
285    
286            protected List<ObjectValuePair<String, InputStream>> getAttachments(
287                    PortletDataContext portletDataContext, Element messageElement,
288                    MBMessage message) {
289    
290                    boolean hasAttachmentsFileEntries = GetterUtil.getBoolean(
291                            messageElement.attributeValue("hasAttachmentsFileEntries"));
292    
293                    if (!hasAttachmentsFileEntries) {
294                            return Collections.emptyList();
295                    }
296    
297                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
298                            new ArrayList<ObjectValuePair<String, InputStream>>();
299    
300                    List<Element> attachmentElements =
301                            portletDataContext.getReferenceDataElements(
302                                    messageElement, DLFileEntry.class,
303                                    PortletDataContext.REFERENCE_TYPE_WEAK);
304    
305                    for (Element attachmentElement : attachmentElements) {
306                            String path = attachmentElement.attributeValue("path");
307    
308                            FileEntry fileEntry =
309                                    (FileEntry)portletDataContext.getZipEntryAsObject(path);
310    
311                            InputStream inputStream = null;
312    
313                            String binPath = attachmentElement.attributeValue("bin-path");
314    
315                            if (Validator.isNull(binPath) &&
316                                    portletDataContext.isPerformDirectBinaryImport()) {
317    
318                                    try {
319                                            inputStream = FileEntryUtil.getContentStream(fileEntry);
320                                    }
321                                    catch (Exception e) {
322                                    }
323                            }
324                            else {
325                                    inputStream = portletDataContext.getZipEntryAsInputStream(
326                                            binPath);
327                            }
328    
329                            if (inputStream == null) {
330                                    if (_log.isWarnEnabled()) {
331                                            _log.warn(
332                                                    "Unable to import attachment for file entry " +
333                                                            fileEntry.getFileEntryId());
334                                    }
335    
336                                    continue;
337                            }
338    
339                            ObjectValuePair<String, InputStream> inputStreamOVP =
340                                    new ObjectValuePair<String, InputStream>(
341                                            fileEntry.getTitle(), inputStream);
342    
343                            inputStreamOVPs.add(inputStreamOVP);
344                    }
345    
346                    if (inputStreamOVPs.isEmpty()) {
347                            _log.error(
348                                    "Could not find attachments for message " +
349                                            message.getMessageId());
350                    }
351    
352                    return inputStreamOVPs;
353            }
354    
355            private static Log _log = LogFactoryUtil.getLog(
356                    MBMessageStagedModelDataHandler.class);
357    
358    }