/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.message.boards.internal.exportimport.data.handler;
import com.liferay.document.library.kernel.model.DLFileEntry;
import com.liferay.document.library.kernel.model.DLFolderConstants;
import com.liferay.exportimport.data.handler.base.BaseStagedModelDataHandler;
import com.liferay.exportimport.kernel.lar.ExportImportPathUtil;
import com.liferay.exportimport.kernel.lar.PortletDataContext;
import com.liferay.exportimport.kernel.lar.StagedModelDataHandler;
import com.liferay.exportimport.kernel.lar.StagedModelDataHandlerUtil;
import com.liferay.exportimport.kernel.lar.StagedModelModifiedDateComparator;
import com.liferay.message.boards.kernel.model.MBCategory;
import com.liferay.message.boards.kernel.model.MBCategoryConstants;
import com.liferay.message.boards.kernel.model.MBDiscussion;
import com.liferay.message.boards.kernel.model.MBMessage;
import com.liferay.message.boards.kernel.model.MBThread;
import com.liferay.message.boards.kernel.service.MBDiscussionLocalService;
import com.liferay.message.boards.kernel.service.MBMessageLocalService;
import com.liferay.message.boards.kernel.service.MBThreadLocalService;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.repository.model.FileEntry;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.trash.TrashHandler;
import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.MapUtil;
import com.liferay.portal.kernel.util.ObjectValuePair;
import com.liferay.portal.kernel.util.StreamUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portlet.documentlibrary.lar.FileEntryUtil;
import com.liferay.ratings.kernel.model.RatingsEntry;
import com.liferay.ratings.kernel.service.RatingsEntryLocalService;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Daniel Kocsis
*/
@Component(immediate = true, service = StagedModelDataHandler.class)
public class MBMessageStagedModelDataHandler
extends BaseStagedModelDataHandler<MBMessage> {
public static final String[] CLASS_NAMES = {MBMessage.class.getName()};
@Override
public void deleteStagedModel(MBMessage message) throws PortalException {
_mbMessageLocalService.deleteMessage(message);
}
@Override
public void deleteStagedModel(
String uuid, long groupId, String className, String extraData)
throws PortalException {
MBMessage message = fetchStagedModelByUuidAndGroupId(uuid, groupId);
if (message != null) {
deleteStagedModel(message);
}
}
@Override
public MBMessage fetchStagedModelByUuidAndGroupId(
String uuid, long groupId) {
return _mbMessageLocalService.fetchMBMessageByUuidAndGroupId(
uuid, groupId);
}
@Override
public List<MBMessage> fetchStagedModelsByUuidAndCompanyId(
String uuid, long companyId) {
return _mbMessageLocalService.getMBMessagesByUuidAndCompanyId(
uuid, companyId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
new StagedModelModifiedDateComparator<MBMessage>());
}
@Override
public String[] getClassNames() {
return CLASS_NAMES;
}
@Override
public String getDisplayName(MBMessage message) {
return message.getSubject();
}
protected MBMessage addDiscussionMessage(
PortletDataContext portletDataContext, long userId, long threadId,
long parentMessageId, MBMessage message,
ServiceContext serviceContext)
throws PortalException {
MBDiscussion discussion = _mbDiscussionLocalService.getThreadDiscussion(
threadId);
MBMessage importedMessage = null;
if (!message.isRoot()) {
importedMessage = _mbMessageLocalService.addDiscussionMessage(
userId, message.getUserName(),
portletDataContext.getScopeGroupId(), discussion.getClassName(),
discussion.getClassPK(), threadId, parentMessageId,
message.getSubject(), message.getBody(), serviceContext);
}
else {
MBThread thread = _mbThreadLocalService.getThread(threadId);
importedMessage = _mbMessageLocalService.getMBMessage(
thread.getRootMessageId());
}
return importedMessage;
}
@Override
protected void doExportStagedModel(
PortletDataContext portletDataContext, MBMessage message)
throws Exception {
if (message.isDiscussion()) {
MBDiscussion discussion = _mbDiscussionLocalService.getDiscussion(
message.getClassName(), message.getClassPK());
StagedModelDataHandlerUtil.exportReferenceStagedModel(
portletDataContext, message, discussion,
PortletDataContext.REFERENCE_TYPE_PARENT);
// Ratings that belong to discussion messages cannot be exported
// automatically because of the special class name and class PK pair
List<RatingsEntry> ratingsEntries =
_ratingsEntryLocalService.getEntries(
MBDiscussion.class.getName(), message.getMessageId());
for (RatingsEntry ratingsEntry : ratingsEntries) {
StagedModelDataHandlerUtil.exportReferenceStagedModel(
portletDataContext, message, ratingsEntry,
PortletDataContext.REFERENCE_TYPE_WEAK);
}
}
else if (message.getCategoryId() !=
MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
StagedModelDataHandlerUtil.exportReferenceStagedModel(
portletDataContext, message, message.getCategory(),
PortletDataContext.REFERENCE_TYPE_PARENT);
}
if (!message.isRoot()) {
MBMessage parentMessage = _mbMessageLocalService.getMessage(
message.getParentMessageId());
StagedModelDataHandlerUtil.exportReferenceStagedModel(
portletDataContext, message, parentMessage,
PortletDataContext.REFERENCE_TYPE_PARENT);
}
message.setPriority(message.getPriority());
MBThread thread = message.getThread();
Element messageElement = portletDataContext.getExportDataElement(
message);
messageElement.addAttribute(
"question", String.valueOf(thread.isQuestion()));
messageElement.addAttribute("threadUuid", thread.getUuid());
boolean hasAttachmentsFileEntries = false;
if (message.getAttachmentsFileEntriesCount() > 0) {
hasAttachmentsFileEntries = true;
}
messageElement.addAttribute(
"hasAttachmentsFileEntries",
String.valueOf(hasAttachmentsFileEntries));
if (hasAttachmentsFileEntries) {
for (FileEntry fileEntry : message.getAttachmentsFileEntries()) {
StagedModelDataHandlerUtil.exportReferenceStagedModel(
portletDataContext, message, fileEntry,
PortletDataContext.REFERENCE_TYPE_WEAK);
}
long folderId = message.getAttachmentsFolderId();
if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
message.setAttachmentsFolderId(folderId);
}
}
portletDataContext.addClassedModel(
messageElement, ExportImportPathUtil.getModelPath(message),
message);
}
@Override
protected void doImportStagedModel(
PortletDataContext portletDataContext, MBMessage message)
throws Exception {
if (!message.isRoot()) {
StagedModelDataHandlerUtil.importReferenceStagedModel(
portletDataContext, message, MBMessage.class,
message.getParentMessageId());
}
long userId = portletDataContext.getUserId(message.getUserUuid());
Map<Long, Long> categoryIds =
(Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
MBCategory.class);
long parentCategoryId = MapUtil.getLong(
categoryIds, message.getCategoryId(), message.getCategoryId());
Map<Long, Long> threadIds =
(Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
MBThread.class);
long threadId = MapUtil.getLong(threadIds, message.getThreadId(), 0);
Element messageElement =
portletDataContext.getImportDataStagedModelElement(message);
if (threadId == 0) {
String threadUuid = messageElement.attributeValue("threadUuid");
MBThread thread =
_mbThreadLocalService.fetchMBThreadByUuidAndGroupId(
threadUuid, portletDataContext.getScopeGroupId());
if (thread != null) {
threadId = thread.getThreadId();
}
}
Map<Long, Long> messageIds =
(Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
MBMessage.class);
long parentMessageId = MapUtil.getLong(
messageIds, message.getParentMessageId(),
message.getParentMessageId());
List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
getAttachments(portletDataContext, messageElement, message);
try {
ServiceContext serviceContext =
portletDataContext.createServiceContext(message);
MBMessage importedMessage = null;
if (portletDataContext.isDataStrategyMirror()) {
MBMessage existingMessage = fetchStagedModelByUuidAndGroupId(
message.getUuid(), portletDataContext.getScopeGroupId());
if (existingMessage == null) {
serviceContext.setUuid(message.getUuid());
if (message.isDiscussion()) {
importedMessage = addDiscussionMessage(
portletDataContext, userId, threadId,
parentMessageId, message, serviceContext);
}
else {
importedMessage = _mbMessageLocalService.addMessage(
userId, message.getUserName(),
portletDataContext.getScopeGroupId(),
parentCategoryId, threadId, parentMessageId,
message.getSubject(), message.getBody(),
message.getFormat(), inputStreamOVPs,
message.getAnonymous(), message.getPriority(),
message.getAllowPingbacks(), serviceContext);
}
}
else {
if (!message.isRoot() && message.isDiscussion()) {
MBDiscussion discussion =
_mbDiscussionLocalService.getThreadDiscussion(
threadId);
importedMessage =
_mbMessageLocalService.updateDiscussionMessage(
userId, existingMessage.getMessageId(),
discussion.getClassName(),
discussion.getClassPK(), message.getSubject(),
message.getBody(), serviceContext);
}
else {
importedMessage = _mbMessageLocalService.updateMessage(
userId, existingMessage.getMessageId(),
message.getSubject(), message.getBody(),
inputStreamOVPs, new ArrayList<String>(),
message.getPriority(), message.getAllowPingbacks(),
serviceContext);
}
}
}
else {
if (message.isDiscussion()) {
importedMessage = addDiscussionMessage(
portletDataContext, userId, threadId, parentMessageId,
message, serviceContext);
}
else {
importedMessage = _mbMessageLocalService.addMessage(
userId, message.getUserName(),
portletDataContext.getScopeGroupId(), parentCategoryId,
threadId, parentMessageId, message.getSubject(),
message.getBody(), message.getFormat(), inputStreamOVPs,
message.getAnonymous(), message.getPriority(),
message.getAllowPingbacks(), serviceContext);
}
}
importedMessage = _updateAnswer(message, importedMessage);
if (importedMessage.isRoot() && !importedMessage.isDiscussion()) {
_mbThreadLocalService.updateQuestion(
importedMessage.getThreadId(),
GetterUtil.getBoolean(
messageElement.attributeValue("question")));
}
if (message.isDiscussion()) {
Map<Long, Long> discussionIds =
(Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
MBDiscussion.class);
discussionIds.put(
message.getMessageId(), importedMessage.getMessageId());
}
threadIds.put(message.getThreadId(), importedMessage.getThreadId());
// Keep thread UUID
MBThread thread = importedMessage.getThread();
thread.setUuid(messageElement.attributeValue("threadUuid"));
_mbThreadLocalService.updateMBThread(thread);
portletDataContext.importClassedModel(message, importedMessage);
}
finally {
for (ObjectValuePair<String, InputStream> inputStreamOVP :
inputStreamOVPs) {
InputStream inputStream = inputStreamOVP.getValue();
StreamUtil.cleanUp(inputStream);
}
}
}
@Override
protected void doRestoreStagedModel(
PortletDataContext portletDataContext, MBMessage message)
throws Exception {
long userId = portletDataContext.getUserId(message.getUserUuid());
MBMessage existingMessage = fetchStagedModelByUuidAndGroupId(
message.getUuid(), portletDataContext.getScopeGroupId());
if (existingMessage == null) {
return;
}
if (existingMessage.isInTrash()) {
TrashHandler trashHandler =
TrashHandlerRegistryUtil.getTrashHandler(
MBMessage.class.getName());
if (trashHandler.isRestorable(existingMessage.getMessageId())) {
trashHandler.restoreTrashEntry(
userId, existingMessage.getMessageId());
}
}
if (existingMessage.isInTrashContainer()) {
MBThread existingThread = existingMessage.getThread();
TrashHandler trashHandler =
TrashHandlerRegistryUtil.getTrashHandler(
MBThread.class.getName());
if (trashHandler.isRestorable(existingThread.getThreadId())) {
trashHandler.restoreTrashEntry(
userId, existingThread.getThreadId());
}
}
}
protected List<ObjectValuePair<String, InputStream>> getAttachments(
PortletDataContext portletDataContext, Element messageElement,
MBMessage message) {
boolean hasAttachmentsFileEntries = GetterUtil.getBoolean(
messageElement.attributeValue("hasAttachmentsFileEntries"));
if (!hasAttachmentsFileEntries) {
return Collections.emptyList();
}
List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
new ArrayList<>();
List<Element> attachmentElements =
portletDataContext.getReferenceDataElements(
messageElement, DLFileEntry.class,
PortletDataContext.REFERENCE_TYPE_WEAK);
for (Element attachmentElement : attachmentElements) {
String path = attachmentElement.attributeValue("path");
FileEntry fileEntry =
(FileEntry)portletDataContext.getZipEntryAsObject(path);
InputStream inputStream = null;
String binPath = attachmentElement.attributeValue("bin-path");
if (Validator.isNull(binPath) &&
portletDataContext.isPerformDirectBinaryImport()) {
try {
inputStream = FileEntryUtil.getContentStream(fileEntry);
}
catch (Exception e) {
}
}
else {
inputStream = portletDataContext.getZipEntryAsInputStream(
binPath);
}
if (inputStream == null) {
if (_log.isWarnEnabled()) {
_log.warn(
"Unable to import attachment for file entry " +
fileEntry.getFileEntryId());
}
continue;
}
ObjectValuePair<String, InputStream> inputStreamOVP =
new ObjectValuePair<>(fileEntry.getTitle(), inputStream);
inputStreamOVPs.add(inputStreamOVP);
}
if (inputStreamOVPs.isEmpty()) {
_log.error(
"Could not find attachments for message " +
message.getMessageId());
}
return inputStreamOVPs;
}
@Reference(unbind = "-")
protected void setMBDiscussionLocalService(
MBDiscussionLocalService mbDiscussionLocalService) {
_mbDiscussionLocalService = mbDiscussionLocalService;
}
@Reference(unbind = "-")
protected void setMBMessageLocalService(
MBMessageLocalService mbMessageLocalService) {
_mbMessageLocalService = mbMessageLocalService;
}
@Reference(unbind = "-")
protected void setMBThreadLocalService(
MBThreadLocalService mbThreadLocalService) {
_mbThreadLocalService = mbThreadLocalService;
}
@Reference(unbind = "-")
protected void setRatingsEntryLocalService(
RatingsEntryLocalService ratingsEntryLocalService) {
_ratingsEntryLocalService = ratingsEntryLocalService;
}
private MBMessage _updateAnswer(
MBMessage message, MBMessage importedMessage)
throws PortalException {
if (importedMessage.isAnswer() == message.isAnswer()) {
return importedMessage;
}
Date modifiedDate = importedMessage.getModifiedDate();
_mbMessageLocalService.updateAnswer(
importedMessage, message.isAnswer(), false);
importedMessage = _mbMessageLocalService.fetchMBMessage(
importedMessage.getMessageId());
importedMessage.setModifiedDate(modifiedDate);
_mbMessageLocalService.updateMBMessage(importedMessage);
return importedMessage;
}
private static final Log _log = LogFactoryUtil.getLog(
MBMessageStagedModelDataHandler.class);
private MBDiscussionLocalService _mbDiscussionLocalService;
private MBMessageLocalService _mbMessageLocalService;
private MBThreadLocalService _mbThreadLocalService;
private RatingsEntryLocalService _ratingsEntryLocalService;
}