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