package fi.otavanopisto.muikku.plugins.communicator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import javax.inject.Inject;
import org.apache.commons.collections.CollectionUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Entities.EscapeMode;
import org.jsoup.safety.Cleaner;
import org.jsoup.safety.Whitelist;
import fi.otavanopisto.muikku.model.base.Tag;
import fi.otavanopisto.muikku.model.users.UserEntity;
import fi.otavanopisto.muikku.model.users.UserGroupEntity;
import fi.otavanopisto.muikku.model.users.UserGroupUserEntity;
import fi.otavanopisto.muikku.model.users.UserSchoolDataIdentifier;
import fi.otavanopisto.muikku.model.workspace.WorkspaceEntity;
import fi.otavanopisto.muikku.model.workspace.WorkspaceRoleArchetype;
import fi.otavanopisto.muikku.model.workspace.WorkspaceUserEntity;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageCategoryDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageIdDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageIdLabelDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageRecipientDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageRecipientUserGroupDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageRecipientWorkspaceGroupDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageSignatureDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorMessageTemplateDAO;
import fi.otavanopisto.muikku.plugins.communicator.dao.CommunicatorUserLabelDAO;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorLabel;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessage;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageCategory;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageId;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageIdLabel;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageRecipient;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageRecipientUserGroup;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageRecipientWorkspaceGroup;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageSignature;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageTemplate;
import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorUserLabel;
import fi.otavanopisto.muikku.users.UserGroupEntityController;
import fi.otavanopisto.muikku.users.WorkspaceUserEntityController;
public class CommunicatorController {
@Inject
private UserGroupEntityController userGroupEntityController;
@Inject
private WorkspaceUserEntityController workspaceUserEntityController;
@Inject
private CommunicatorMessageDAO communicatorMessageDAO;
@Inject
private CommunicatorMessageCategoryDAO communicatorMessageCategoryDAO;
@Inject
private CommunicatorMessageRecipientDAO communicatorMessageRecipientDAO;
@Inject
private CommunicatorMessageIdDAO communicatorMessageIdDAO;
@Inject
private CommunicatorMessageTemplateDAO communicatorMessageTemplateDAO;
@Inject
private CommunicatorMessageSignatureDAO communicatorMessageSignatureDAO;
@Inject
private CommunicatorUserLabelDAO communicatorUserLabelDAO;
@Inject
private CommunicatorMessageIdLabelDAO communicatorMessageIdLabelDAO;
@Inject
private CommunicatorMessageRecipientUserGroupDAO communicatorMessageRecipientUserGroupDAO;
@Inject
private CommunicatorMessageRecipientWorkspaceGroupDAO communicatorMessageRecipientWorkspaceGroupDAO;
private String clean(String html) {
Document doc = Jsoup.parseBodyFragment(html);
doc = new Cleaner(
Whitelist.relaxed()
.addAttributes("a", "target")
.addAttributes("img", "width", "height", "style")
.addAttributes("i", "class")
).clean(doc);
doc.outputSettings().escapeMode(EscapeMode.xhtml);
return doc.body().html();
}
public List<CommunicatorMessage> listReceivedItems(UserEntity userEntity, CommunicatorLabel label, boolean onlyUnread, Integer firstResult, Integer maxResults) {
return communicatorMessageDAO.listThreadsInInbox(userEntity, label, onlyUnread, firstResult, maxResults);
}
public List<CommunicatorMessage> listReceivedItems(UserEntity userEntity, boolean onlyUnread, Integer firstResult, Integer maxResults) {
return communicatorMessageDAO.listThreadsInInbox(userEntity, null, onlyUnread, firstResult, maxResults);
}
public List<CommunicatorMessage> listSentItems(UserEntity userEntity, Integer firstResult, Integer maxResults) {
return communicatorMessageDAO.listThreadsInSent(userEntity, firstResult, maxResults);
}
public List<CommunicatorMessageRecipient> listReceivedItemsByUserAndRead(UserEntity userEntity, boolean read, boolean trashed) {
return communicatorMessageRecipientDAO.listByUserAndRead(userEntity, read, trashed);
}
public List<CommunicatorMessage> listTrashItems(UserEntity userEntity, Integer firstResult, Integer maxResults) {
return communicatorMessageDAO.listThreadsInTrash(userEntity, firstResult, maxResults);
}
public CommunicatorMessageCategory persistCategory(String category) {
CommunicatorMessageCategory categoryEntity = communicatorMessageCategoryDAO.findByName(category);
if (categoryEntity == null) {
categoryEntity = communicatorMessageCategoryDAO.create(category);
}
return categoryEntity;
}
public CommunicatorMessageId createMessageId() {
return communicatorMessageIdDAO.create();
}
public CommunicatorMessage createMessage(CommunicatorMessageId communicatorMessageId, UserEntity sender,
List<UserEntity> userRecipients, List<UserGroupEntity> userGroupRecipients,
List<WorkspaceEntity> workspaceStudentRecipients, List<WorkspaceEntity> workspaceTeacherRecipients,
CommunicatorMessageCategory category, String caption, String content, Set<Tag> tags) {
CommunicatorMessage message = communicatorMessageDAO.create(communicatorMessageId, sender.getId(), category, caption, clean(content), new Date(), tags);
// Clean duplicates from recipient list
cleanDuplicateRecipients(userRecipients);
Set<Long> recipientIds = new HashSet<Long>();
for (UserEntity recipient : userRecipients) {
if (!recipientIds.contains(recipient.getId())) {
recipientIds.add(recipient.getId());
communicatorMessageRecipientDAO.create(message, recipient, null);
}
}
if (!CollectionUtils.isEmpty(userGroupRecipients)) {
for (UserGroupEntity userGroup : userGroupRecipients) {
List<UserGroupUserEntity> groupUsers = userGroupEntityController.listUserGroupUserEntitiesByUserGroupEntity(userGroup);
if (!CollectionUtils.isEmpty(groupUsers)) {
CommunicatorMessageRecipientUserGroup groupRecipient = createUserGroupRecipient(userGroup);
for (UserGroupUserEntity groupUser : groupUsers) {
UserSchoolDataIdentifier userSchoolDataIdentifier = groupUser.getUserSchoolDataIdentifier();
UserEntity recipient = userSchoolDataIdentifier.getUserEntity();
if ((recipient != null) && !Objects.equals(sender.getId(), recipient.getId())) {
if (!recipientIds.contains(recipient.getId())) {
recipientIds.add(recipient.getId());
communicatorMessageRecipientDAO.create(message, recipient, groupRecipient);
}
}
}
}
}
}
// Workspace members
if (!CollectionUtils.isEmpty(workspaceStudentRecipients)) {
for (WorkspaceEntity workspaceEntity : workspaceStudentRecipients) {
List<WorkspaceUserEntity> workspaceUsers = workspaceUserEntityController.listWorkspaceUserEntitiesByRoleArchetype(
workspaceEntity, WorkspaceRoleArchetype.STUDENT);
if (!CollectionUtils.isEmpty(workspaceUsers)) {
CommunicatorMessageRecipientWorkspaceGroup groupRecipient = createWorkspaceGroupRecipient(workspaceEntity, WorkspaceRoleArchetype.STUDENT);
for (WorkspaceUserEntity workspaceUserEntity : workspaceUsers) {
UserEntity recipient = workspaceUserEntity.getUserSchoolDataIdentifier().getUserEntity();
if ((recipient != null) && !Objects.equals(sender.getId(), recipient.getId())) {
if (!recipientIds.contains(recipient.getId())) {
recipientIds.add(recipient.getId());
communicatorMessageRecipientDAO.create(message, recipient, groupRecipient);
}
}
}
}
}
}
if (!CollectionUtils.isEmpty(workspaceTeacherRecipients)) {
for (WorkspaceEntity workspaceEntity : workspaceTeacherRecipients) {
List<WorkspaceUserEntity> workspaceUsers = workspaceUserEntityController.listWorkspaceUserEntitiesByRoleArchetype(
workspaceEntity, WorkspaceRoleArchetype.TEACHER);
if (!CollectionUtils.isEmpty(workspaceUsers)) {
CommunicatorMessageRecipientWorkspaceGroup groupRecipient = createWorkspaceGroupRecipient(workspaceEntity, WorkspaceRoleArchetype.TEACHER);
for (WorkspaceUserEntity wosu : workspaceUsers) {
UserEntity recipient = wosu.getUserSchoolDataIdentifier().getUserEntity();
if ((recipient != null) && !Objects.equals(sender.getId(), recipient.getId())) {
if (!recipientIds.contains(recipient.getId())) {
recipientIds.add(recipient.getId());
communicatorMessageRecipientDAO.create(message, recipient, groupRecipient);
}
}
}
}
}
}
return message;
}
private CommunicatorMessageRecipientUserGroup createUserGroupRecipient(UserGroupEntity userGroup) {
return communicatorMessageRecipientUserGroupDAO.create(userGroup);
}
private CommunicatorMessageRecipientWorkspaceGroup createWorkspaceGroupRecipient(WorkspaceEntity workspaceEntity,
WorkspaceRoleArchetype archetype) {
return communicatorMessageRecipientWorkspaceGroupDAO.create(workspaceEntity, archetype);
}
public CommunicatorMessageId findCommunicatorMessageId(Long communicatorMessageId) {
return communicatorMessageIdDAO.findById(communicatorMessageId);
}
public CommunicatorMessage findCommunicatorMessageById(Long communicatorMessageId) {
return communicatorMessageDAO.findById(communicatorMessageId);
}
public CommunicatorMessageRecipient findCommunicatorMessageRecipient(Long id) {
return communicatorMessageRecipientDAO.findById(id);
}
public CommunicatorMessageRecipient findCommunicatorMessageRecipientByMessageAndRecipient(CommunicatorMessage communicatorMessage, UserEntity recipient) {
return communicatorMessageRecipientDAO.findByMessageAndRecipient(communicatorMessage, recipient);
}
/**
* Lists only the individual message recipients
*
* @param communicatorMessage message of which to list the recipients for
* @return a list of recipients
*/
public List<CommunicatorMessageRecipient> listCommunicatorMessageRecipients(CommunicatorMessage communicatorMessage) {
return communicatorMessageRecipientDAO.listByMessage(communicatorMessage);
}
/**
* Lists all CommunicatorMessageRecipients, no matter if they are added by group or as individuals
*
* @param communicatorMessage message of which to list the recipients for
* @return a list of recipients
*/
public List<CommunicatorMessageRecipient> listAllCommunicatorMessageRecipients(CommunicatorMessage communicatorMessage) {
return communicatorMessageRecipientDAO.listByMessageIncludeGroupRecipients(communicatorMessage);
}
public List<CommunicatorMessageRecipientUserGroup> listCommunicatorMessageUserGroupRecipients(CommunicatorMessage communicatorMessage) {
return communicatorMessageRecipientUserGroupDAO.listByMessage(communicatorMessage);
}
public List<CommunicatorMessageRecipientWorkspaceGroup> listCommunicatorMessageWorkspaceGroupRecipients(CommunicatorMessage communicatorMessage) {
return communicatorMessageRecipientWorkspaceGroupDAO.listByMessage(communicatorMessage);
}
public List<CommunicatorMessageRecipient> listCommunicatorMessageRecipientsByUserAndMessage(UserEntity user, CommunicatorMessageId messageId, boolean trashed) {
return communicatorMessageRecipientDAO.listByUserAndMessageId(user, messageId, trashed, false);
}
public Long countMessagesByUserAndMessageId(UserEntity user, CommunicatorMessageId communicatorMessageId, boolean inTrash) {
return communicatorMessageDAO.countMessagesByUserAndMessageId(user, communicatorMessageId, inTrash);
}
public List<CommunicatorMessageTemplate> listMessageTemplates(UserEntity user) {
return communicatorMessageTemplateDAO.listByUser(user);
}
public List<CommunicatorMessageSignature> listMessageSignatures(UserEntity user) {
return communicatorMessageSignatureDAO.listByUser(user);
}
public CommunicatorMessageTemplate getMessageTemplate(Long id) {
return communicatorMessageTemplateDAO.findById(id);
}
public CommunicatorMessageSignature getMessageSignature(Long id) {
return communicatorMessageSignatureDAO.findById(id);
}
public void deleteMessageTemplate(CommunicatorMessageTemplate messageTemplate) {
communicatorMessageTemplateDAO.delete(messageTemplate);
}
public void deleteMessageSignature(CommunicatorMessageSignature messageSignature) {
communicatorMessageSignatureDAO.delete(messageSignature);
}
public CommunicatorMessageTemplate editMessageTemplate(CommunicatorMessageTemplate messageTemplate, String name, String content) {
return communicatorMessageTemplateDAO.update(messageTemplate, name, content);
}
public CommunicatorMessageSignature editMessageSignature(CommunicatorMessageSignature messageSignature, String name, String signature) {
return communicatorMessageSignatureDAO.update(messageSignature, name, signature);
}
public CommunicatorMessageSignature createMessageSignature(String name, String content, UserEntity user) {
return communicatorMessageSignatureDAO.create(name, content, user);
}
public CommunicatorMessageTemplate createMessageTemplate(String name, String content, UserEntity user) {
return communicatorMessageTemplateDAO.create(name, content, user);
}
public void trashSentMessages(UserEntity user, CommunicatorMessageId messageId) {
List<CommunicatorMessage> sentMessages = communicatorMessageDAO.listMessagesInSentThread(user, messageId, false, false);
for (CommunicatorMessage message : sentMessages) {
communicatorMessageDAO.updateTrashedBySender(message, true);
}
}
public void trashAllThreadMessages(UserEntity user, CommunicatorMessageId messageId) {
List<CommunicatorMessageRecipient> received = communicatorMessageRecipientDAO.listByUserAndMessageId(user, messageId, false, false);
for (CommunicatorMessageRecipient recipient : received) {
communicatorMessageRecipientDAO.updateTrashedByReceiver(recipient, true);
}
List<CommunicatorMessage> sentMessages = communicatorMessageDAO.listMessagesInSentThread(user, messageId, false, false);
for (CommunicatorMessage message : sentMessages) {
communicatorMessageDAO.updateTrashedBySender(message, true);
}
}
public void archiveTrashedMessages(UserEntity user, CommunicatorMessageId threadId) {
List<CommunicatorMessageRecipient> received = communicatorMessageRecipientDAO.listByUserAndMessageId(user, threadId, true, false);
for (CommunicatorMessageRecipient recipient : received) {
communicatorMessageRecipientDAO.updateArchivedByReceiver(recipient, true);
}
List<CommunicatorMessage> sent = communicatorMessageDAO.listMessagesInSentThread(user, threadId, true, false);
for (CommunicatorMessage msg : sent) {
communicatorMessageDAO.updateArchivedBySender(msg, true);
}
}
/**
* List all messages with id user has sent or received.
*
* @param user
* @param messageId
* @return
*/
public List<CommunicatorMessage> listMessagesByMessageId(UserEntity user, CommunicatorMessageId messageId, Boolean trashed) {
Set<CommunicatorMessage> result = new TreeSet<>(new Comparator<CommunicatorMessage>() {
@Override
public int compare(CommunicatorMessage o1, CommunicatorMessage o2) {
if (o1 == null || o1.getId() == null) {
if (o2 == null || o2.getId() == null) {
return 0;
} else {
return -1;
}
}
return o1.getId().compareTo(o2.getId());
}
});
result.addAll(communicatorMessageDAO.listMessagesInSentThread(user, messageId, trashed, false));
result.addAll(communicatorMessageDAO.listMessagesInThread(user, messageId, trashed, false));
return new ArrayList<>(result);
}
public CommunicatorMessageRecipient updateRead(CommunicatorMessageRecipient recipient, boolean value) {
return communicatorMessageRecipientDAO.updateRecipientRead(recipient, value);
}
public CommunicatorMessage postMessage(UserEntity sender, String category, String subject, String content, List<UserEntity> recipients) {
CommunicatorMessageId communicatorMessageId = createMessageId();
// TODO Category not existing at this point would technically indicate an invalid state
CommunicatorMessageCategory categoryEntity = persistCategory(category);
return createMessage(communicatorMessageId, sender, recipients, null, null, null, categoryEntity, subject, content, null);
}
public CommunicatorMessage replyToMessage(UserEntity sender, String category, String subject, String content, List<UserEntity> recipients, CommunicatorMessageId communicatorMessageId) {
CommunicatorMessageCategory categoryEntity = persistCategory(category);
return createMessage(communicatorMessageId, sender, recipients, null, null, null, categoryEntity, subject, content, null);
}
public List<CommunicatorMessage> listAllMessages() {
return communicatorMessageDAO.listAll();
}
public List<CommunicatorMessageRecipient> listAllRecipients() {
return communicatorMessageRecipientDAO.listAll();
}
public List<CommunicatorMessageId> listAllMessageIds() {
return communicatorMessageIdDAO.listAll();
}
/* User Label */
public CommunicatorUserLabel createUserLabel(String name, Long color, UserEntity userEntity) {
return communicatorUserLabelDAO.create(name, color, userEntity);
}
public CommunicatorUserLabel findUserLabelById(Long id) {
return communicatorUserLabelDAO.findById(id);
}
public List<CommunicatorUserLabel> listUserLabelsByUserEntity(UserEntity userEntity) {
return communicatorUserLabelDAO.listByUser(userEntity);
}
public CommunicatorUserLabel updateUserLabel(CommunicatorUserLabel userLabel, String name, Long color) {
return communicatorUserLabelDAO.update(userLabel, name, color);
}
/* MessageIdLabel */
public CommunicatorMessageIdLabel createMessageIdLabel(UserEntity userEntity, CommunicatorMessageId messageId, CommunicatorLabel label) {
return communicatorMessageIdLabelDAO.create(userEntity, messageId, label);
}
public CommunicatorMessageIdLabel findMessageIdLabelById(Long id) {
return communicatorMessageIdLabelDAO.findById(id);
}
public CommunicatorMessageIdLabel findMessageIdLabel(UserEntity userEntity, CommunicatorMessageId messageId,
CommunicatorLabel label) {
return communicatorMessageIdLabelDAO.findBy(userEntity, messageId, label);
}
public List<CommunicatorMessageIdLabel> listMessageIdLabelsByUserEntity(UserEntity userEntity, CommunicatorMessageId messageId) {
return communicatorMessageIdLabelDAO.listByUserAndMessageId(userEntity, messageId);
}
public void delete(CommunicatorMessageIdLabel messageIdLabel) {
communicatorMessageIdLabelDAO.delete(messageIdLabel);
}
/* DELETE */
public void delete(CommunicatorMessage icm) {
communicatorMessageDAO.delete(icm);
}
public void delete(CommunicatorMessageRecipient cmr) {
communicatorMessageRecipientDAO.delete(cmr);
}
public void delete(CommunicatorMessageId id) {
communicatorMessageIdDAO.delete(id);
}
public void delete(CommunicatorUserLabel communicatorUserLabel) {
List<CommunicatorMessageIdLabel> labels = communicatorMessageIdLabelDAO.listByLabel(communicatorUserLabel);
for (CommunicatorMessageIdLabel label : labels) {
delete(label);
}
communicatorUserLabelDAO.delete(communicatorUserLabel);
}
/**
* Cleans list of UserEntities so that there are no duplicates present. Returns the original list.
*
* @param userEntities
* @return
*/
public void cleanDuplicateRecipients(List<UserEntity> userEntities) {
Set<Long> userIds = new HashSet<Long>(userEntities.size());
for (int i = userEntities.size() - 1; i >= 0; i--) {
if (userEntities.get(i) != null) {
Long userId = userEntities.get(i).getId();
if (!userIds.contains(userId))
userIds.add(userId);
else
userEntities.remove(i);
} else
userEntities.remove(i);
}
}
public void removeRecipient(List<UserEntity> userEntities, UserEntity userEntity) {
for (int i = userEntities.size() - 1; i >= 0; i--) {
if (userEntities.get(i) != null) {
Long userId = userEntities.get(i).getId();
if (userId.equals(userEntity.getId()))
userEntities.remove(i);
}
}
}
public CommunicatorMessageId findOlderThreadId(UserEntity userEntity, CommunicatorMessageId threadId, CommunicatorFolderType type, CommunicatorLabel label) {
return communicatorMessageDAO.findOlderThreadId(userEntity, threadId, type, label);
}
public CommunicatorMessageId findNewerThreadId(UserEntity userEntity, CommunicatorMessageId threadId, CommunicatorFolderType type, CommunicatorLabel label) {
return communicatorMessageDAO.findNewerThreadId(userEntity, threadId, type, label);
}
}