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                    if (!message.isRoot()) {
099                            MBMessage parentMessage = MBMessageLocalServiceUtil.getMessage(
100                                    message.getParentMessageId());
101    
102                            StagedModelDataHandlerUtil.exportReferenceStagedModel(
103                                    portletDataContext, message, parentMessage,
104                                    PortletDataContext.REFERENCE_TYPE_PARENT);
105                    }
106    
107                    message.setPriority(message.getPriority());
108    
109                    MBThread thread = message.getThread();
110    
111                    Element messageElement = portletDataContext.getExportDataElement(
112                            message);
113    
114                    messageElement.addAttribute(
115                            "question", String.valueOf(thread.isQuestion()));
116    
117                    boolean hasAttachmentsFileEntries =
118                            message.getAttachmentsFileEntriesCount() > 0;
119    
120                    messageElement.addAttribute(
121                            "hasAttachmentsFileEntries",
122                            String.valueOf(hasAttachmentsFileEntries));
123    
124                    if (hasAttachmentsFileEntries) {
125                            for (FileEntry fileEntry : message.getAttachmentsFileEntries()) {
126                                    StagedModelDataHandlerUtil.exportReferenceStagedModel(
127                                            portletDataContext, message, fileEntry,
128                                            PortletDataContext.REFERENCE_TYPE_WEAK);
129                            }
130    
131                            long folderId = message.getAttachmentsFolderId();
132    
133                            if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
134                                    message.setAttachmentsFolderId(folderId);
135                            }
136                    }
137    
138                    portletDataContext.addClassedModel(
139                            messageElement, ExportImportPathUtil.getModelPath(message),
140                            message);
141            }
142    
143            @Override
144            protected void doImportStagedModel(
145                            PortletDataContext portletDataContext, MBMessage message)
146                    throws Exception {
147    
148                    if (!message.isRoot()) {
149                            StagedModelDataHandlerUtil.importReferenceStagedModel(
150                                    portletDataContext, message, MBMessage.class,
151                                    message.getParentMessageId());
152                    }
153    
154                    long userId = portletDataContext.getUserId(message.getUserUuid());
155    
156                    String userName = message.getUserName();
157    
158                    Map<Long, Long> categoryIds =
159                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
160                                    MBCategory.class);
161    
162                    long parentCategoryId = MapUtil.getLong(
163                            categoryIds, message.getCategoryId(), message.getCategoryId());
164    
165                    Map<Long, Long> threadIds =
166                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
167                                    MBThread.class);
168    
169                    long threadId = MapUtil.getLong(threadIds, message.getThreadId(), 0);
170    
171                    Map<Long, Long> messageIds =
172                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
173                                    MBMessage.class);
174    
175                    long parentMessageId = MapUtil.getLong(
176                            messageIds, message.getParentMessageId(),
177                            message.getParentMessageId());
178    
179                    Element element = portletDataContext.getImportDataStagedModelElement(
180                            message);
181    
182                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
183                            getAttachments(portletDataContext, element, message);
184    
185                    try {
186                            ServiceContext serviceContext =
187                                    portletDataContext.createServiceContext(message);
188    
189                            if ((parentCategoryId !=
190                                            MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
191                                    (parentCategoryId !=
192                                            MBCategoryConstants.DISCUSSION_CATEGORY_ID) &&
193                                    (parentCategoryId == message.getCategoryId())) {
194    
195                                    StagedModelDataHandlerUtil.importReferenceStagedModel(
196                                            portletDataContext, message, MBCategory.class,
197                                            parentCategoryId);
198    
199                                    parentCategoryId = MapUtil.getLong(
200                                            categoryIds, message.getCategoryId(),
201                                            message.getCategoryId());
202                            }
203    
204                            MBMessage importedMessage = null;
205    
206                            if (portletDataContext.isDataStrategyMirror()) {
207                                    MBMessage existingMessage =
208                                            MBMessageLocalServiceUtil.fetchMBMessageByUuidAndGroupId(
209                                                    message.getUuid(),
210                                                    portletDataContext.getScopeGroupId());
211    
212                                    if (existingMessage == null) {
213                                            serviceContext.setUuid(message.getUuid());
214    
215                                            importedMessage = MBMessageLocalServiceUtil.addMessage(
216                                                    userId, userName, portletDataContext.getScopeGroupId(),
217                                                    parentCategoryId, threadId, parentMessageId,
218                                                    message.getSubject(), message.getBody(),
219                                                    message.getFormat(), inputStreamOVPs,
220                                                    message.getAnonymous(), message.getPriority(),
221                                                    message.getAllowPingbacks(), serviceContext);
222                                    }
223                                    else {
224                                            importedMessage = MBMessageLocalServiceUtil.updateMessage(
225                                                    userId, existingMessage.getMessageId(),
226                                                    message.getSubject(), message.getBody(),
227                                                    inputStreamOVPs, new ArrayList<String>(),
228                                                    message.getPriority(), message.getAllowPingbacks(),
229                                                    serviceContext);
230                                    }
231                            }
232                            else {
233                                    importedMessage = MBMessageLocalServiceUtil.addMessage(
234                                            userId, userName, portletDataContext.getScopeGroupId(),
235                                            parentCategoryId, threadId, parentMessageId,
236                                            message.getSubject(), message.getBody(),
237                                            message.getFormat(), inputStreamOVPs,
238                                            message.getAnonymous(), message.getPriority(),
239                                            message.getAllowPingbacks(), serviceContext);
240                            }
241    
242                            importedMessage.setAnswer(message.getAnswer());
243    
244                            if (importedMessage.isRoot()) {
245                                    MBThreadLocalServiceUtil.updateQuestion(
246                                            importedMessage.getThreadId(),
247                                            GetterUtil.getBoolean(element.attributeValue("question")));
248                            }
249    
250                            threadIds.put(message.getThreadId(), importedMessage.getThreadId());
251    
252                            portletDataContext.importClassedModel(message, importedMessage);
253                    }
254                    finally {
255                            for (ObjectValuePair<String, InputStream> inputStreamOVP :
256                                            inputStreamOVPs) {
257    
258                                    InputStream inputStream = inputStreamOVP.getValue();
259    
260                                    StreamUtil.cleanUp(inputStream);
261                            }
262                    }
263            }
264    
265            @Override
266            protected void doRestoreStagedModel(
267                            PortletDataContext portletDataContext, MBMessage message)
268                    throws Exception {
269    
270                    long userId = portletDataContext.getUserId(message.getUserUuid());
271    
272                    MBMessage existingMessage =
273                            MBMessageLocalServiceUtil.fetchMBMessageByUuidAndGroupId(
274                                    message.getUuid(), portletDataContext.getScopeGroupId());
275    
276                    if (existingMessage == null) {
277                            return;
278                    }
279    
280                    if (existingMessage.isInTrash()) {
281                            TrashHandler trashHandler = existingMessage.getTrashHandler();
282    
283                            if (trashHandler.isRestorable(existingMessage.getMessageId())) {
284                                    trashHandler.restoreTrashEntry(
285                                            userId, existingMessage.getMessageId());
286                            }
287                    }
288    
289                    if (existingMessage.isInTrashContainer()) {
290                            MBThread existingThread = existingMessage.getThread();
291    
292                            TrashHandler trashHandler = existingThread.getTrashHandler();
293    
294                            if (trashHandler.isRestorable(existingThread.getThreadId())) {
295                                    trashHandler.restoreTrashEntry(
296                                            userId, existingThread.getThreadId());
297                            }
298                    }
299            }
300    
301            protected List<ObjectValuePair<String, InputStream>> getAttachments(
302                    PortletDataContext portletDataContext, Element messageElement,
303                    MBMessage message) {
304    
305                    boolean hasAttachmentsFileEntries = GetterUtil.getBoolean(
306                            messageElement.attributeValue("hasAttachmentsFileEntries"));
307    
308                    if (!hasAttachmentsFileEntries) {
309                            return Collections.emptyList();
310                    }
311    
312                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
313                            new ArrayList<ObjectValuePair<String, InputStream>>();
314    
315                    List<Element> attachmentElements =
316                            portletDataContext.getReferenceDataElements(
317                                    messageElement, DLFileEntry.class,
318                                    PortletDataContext.REFERENCE_TYPE_WEAK);
319    
320                    for (Element attachmentElement : attachmentElements) {
321                            String path = attachmentElement.attributeValue("path");
322    
323                            FileEntry fileEntry =
324                                    (FileEntry)portletDataContext.getZipEntryAsObject(path);
325    
326                            InputStream inputStream = null;
327    
328                            String binPath = attachmentElement.attributeValue("bin-path");
329    
330                            if (Validator.isNull(binPath) &&
331                                    portletDataContext.isPerformDirectBinaryImport()) {
332    
333                                    try {
334                                            inputStream = FileEntryUtil.getContentStream(fileEntry);
335                                    }
336                                    catch (Exception e) {
337                                    }
338                            }
339                            else {
340                                    inputStream = portletDataContext.getZipEntryAsInputStream(
341                                            binPath);
342                            }
343    
344                            if (inputStream == null) {
345                                    if (_log.isWarnEnabled()) {
346                                            _log.warn(
347                                                    "Unable to import attachment for file entry " +
348                                                            fileEntry.getFileEntryId());
349                                    }
350    
351                                    continue;
352                            }
353    
354                            ObjectValuePair<String, InputStream> inputStreamOVP =
355                                    new ObjectValuePair<String, InputStream>(
356                                            fileEntry.getTitle(), inputStream);
357    
358                            inputStreamOVPs.add(inputStreamOVP);
359                    }
360    
361                    if (inputStreamOVPs.isEmpty()) {
362                            _log.error(
363                                    "Could not find attachments for message " +
364                                            message.getMessageId());
365                    }
366    
367                    return inputStreamOVPs;
368            }
369    
370            private static Log _log = LogFactoryUtil.getLog(
371                    MBMessageStagedModelDataHandler.class);
372    
373    }