com.liferay.mail.vaadin.FolderTree.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.mail.vaadin.FolderTree.java

Source

/**
 * Copyright (c) 2000-2011 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.mail.vaadin;

import com.liferay.mail.MailException;
import com.liferay.mail.mailbox.Mailbox;
import com.liferay.mail.mailbox.MailboxFactoryUtil;
import com.liferay.mail.model.Account;
import com.liferay.mail.model.Folder;
import com.liferay.mail.model.Message;
import com.liferay.mail.service.AccountLocalServiceUtil;
import com.liferay.mail.service.FolderLocalServiceUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;

import com.vaadin.data.Container;
import com.vaadin.data.Property;
import com.vaadin.event.Action;
import com.vaadin.event.DataBoundTransferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.event.dd.acceptcriteria.And;
import com.vaadin.event.dd.acceptcriteria.Not;
import com.vaadin.event.dd.acceptcriteria.Or;
import com.vaadin.event.dd.acceptcriteria.SourceIs;
import com.vaadin.event.dd.acceptcriteria.TargetDetailIs;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Tree;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author Henri Sara
 */
public class FolderTree extends Tree implements DropHandler, Action.Handler {

    private static class AccountAction extends Action {

        private final Long accountId;

        public AccountAction(String captionKey, Long accountId) {
            super(Lang.get(captionKey));
            this.accountId = accountId;
        }

        public Long getAccountId() {
            return accountId;
        }

    }

    private static class FolderAction extends Action {

        private final Folder folder;

        public FolderAction(String captionKey, Folder folder) {
            super(Lang.get(captionKey));
            this.folder = folder;
        }

        public Folder getFolder() {
            return folder;
        }

    }

    private FolderChangeListener folderChangedListener;

    private MessageList messageList;

    public FolderTree(FolderChangeListener listener, MessageList msgList) {

        super("");
        this.folderChangedListener = listener;
        this.messageList = msgList;

        setSizeFull();
        setSelectable(true);
        setNullSelectionAllowed(false);
        setImmediate(true);
        setMultiSelect(false);

        // Only add drag&drop support if the msgList is enabled
        if (messageList != null) {
            setDropHandler(this);
        }

        // Initiate folder selected event when a folder is selected
        addListener(new Property.ValueChangeListener() {

            public void valueChange(Property.ValueChangeEvent event) {

                if (folderChangedListener != null) {
                    folderChangedListener.selectedFolderChanged(
                            ((FolderContainer) getContainerDataSource()).getFolder(event.getProperty().getValue()));
                }
            }

        });

        addActionHandler(this);
    }

    @Override
    public void setContainerDataSource(Container newDataSource) {

        super.setContainerDataSource(newDataSource);

        if (newDataSource instanceof FolderContainer) {
            setItemCaptionPropertyId(FolderContainer.getCaptionPropertyId());
            setItemIconPropertyId(FolderContainer.getIconPropertyId());
        }
    }

    private FolderContainer getFolderContainer() {

        return (FolderContainer) getContainerDataSource();
    }

    public void expand(Long accountId, Long folderId) {

        if (accountId == null) {
            return;
        }
        expandItemsRecursively(getFolderContainer().getAccountItemId(accountId));

    }

    public void selectFolder(Long accountId, Long folderId) {

        if (accountId == null || folderId == null) {
            return;
        }
        select(getFolderContainer().getFolderItemId(accountId, folderId));
    }

    public void drop(DragAndDropEvent dropEvent) {

        DataBoundTransferable tr = (DataBoundTransferable) dropEvent.getTransferable();

        Object itemId = tr.getItemId();

        // Get the details of the drop target
        TreeTargetDetails details = (TreeTargetDetails) dropEvent.getTargetDetails();

        if (rootItemIds().contains(details.getItemIdOver())) {
            // TODO should do with criteria instead
            return;
        }

        // Get the target folder
        Folder targetFolder = getFolderContainer().getFolder(details.getItemIdOver());

        // support dropping multiple messages at once
        if (itemId instanceof Message) {
            Message msg = (Message) itemId;
            List<Message> messages = new ArrayList<Message>();
            if (tr.getSourceComponent() instanceof MessageListTable) {
                // possible multi-row drop, need to get selection from table
                MessageListTable table = (MessageListTable) tr.getSourceComponent();
                Collection<Message> value = (Collection) table.getValue();
                messages.addAll(value);
            }
            // single message drop
            if (messages.isEmpty()) {
                messages.add(msg);
            }

            // Move message
            try {
                MessageUtil.moveMessagesTo(messages, targetFolder);
                Controller.get().showInfo(Lang.get("messages-have-been-moved"));
            } catch (PortalException e) {
                Controller.get().showError(Lang.get("unable-to-move-messages"), e);
            } catch (SystemException e) {
                Controller.get().showError(Lang.get("unable-to-move-messages"), e);
            }

            if (folderChangedListener != null) {
                Folder currentFolder = getFolderContainer().getFolder(getValue());
                folderChangedListener.selectedFolderChanged(currentFolder);
            }
        }
    }

    public AcceptCriterion getAcceptCriterion() {
        TargetDetailIs isMiddle = new TargetDetailIs("detail", "MIDDLE");
        SourceIs isFromMessageList = new SourceIs(messageList.getTable());

        List<TargetItemIs> rootItemCriterias = new ArrayList<TargetItemIs>();
        for (Object root : rootItemIds()) {
            rootItemCriterias.add(new TargetItemIs(this, root));
        }
        Or or = new Or(rootItemCriterias.toArray(new TargetItemIs[rootItemCriterias.size()]));
        Not notRootItem = new Not(or);

        return new And(isMiddle, isFromMessageList, notRootItem);
    }

    public Action[] getActions(Object target, Object sender) {
        Folder folder = getFolderContainer().getFolder(target);
        Account account = getFolderContainer().getAccount(target);
        ArrayList<Action> actions = new ArrayList<Action>();
        boolean modifiable = getFolderContainer().isModifiable(target);

        if (account != null && folder == null) {
            actions.add(new AccountAction("create-folder", account.getAccountId()));
        }
        if (folder != null && modifiable) {
            actions.add(new FolderAction("rename-folder", folder));
            actions.add(new FolderAction("delete-folder", folder));
        }

        return actions.toArray(new Action[0]);
    }

    public void handleAction(Action action, Object sender, Object target) {
        if (action instanceof AccountAction) {
            handleAccountAction((AccountAction) action);
        } else if (action instanceof FolderAction) {
            handleFolderAction((FolderAction) action);
        }
        // else do nothing
    }

    public void handleAccountAction(AccountAction action) {
        final Long accountId = action.getAccountId();
        if (accountId == null) {
            return;
        }

        if (Lang.get("create-folder").equals(action.getCaption())) {
            String title = Lang.get("create-folder");
            String message = Lang.get("please-enter-a-folder-name");
            final ConfirmDialog confirm = new ConfirmDialog(Lang.get("confirm"), title, message);
            final TextField newNameField = new TextField();
            newNameField.setNullRepresentation("");
            newNameField.setValue("new folder");
            confirm.addExtraComponent(newNameField);

            confirm.addConfirmButtonListener(new ClickListener() {

                public void buttonClick(ClickEvent event) {
                    String newName = (String) newNameField.getValue();
                    if (newName != null && !"".equals(newName)) {
                        confirm.closeDialog();

                        addFolder(accountId, newName);

                        synchronizeAccount(accountId, Controller.get());
                        refresh();
                    } else {
                        Controller.get().showError(Lang.get("please-enter-a-folder-name"));
                    }
                }
            });

            Controller.get().getApplication().getMainWindow().addWindow(confirm);
        }
    }

    public void handleFolderAction(FolderAction action) {
        final Folder folder = action.getFolder();
        if (folder == null) {
            return;
        }

        if (Lang.get("rename-folder").equals(action.getCaption())) {
            String title = Lang.get("rename-folder");
            String message = Lang.get("please-enter-a-new-folder-name");
            final ConfirmDialog confirm = new ConfirmDialog(Lang.get("confirm"), title, message);
            final TextField newNameField = new TextField();
            newNameField.setNullRepresentation("");
            newNameField.setValue(folder.getDisplayName());
            confirm.addExtraComponent(newNameField);

            confirm.addConfirmButtonListener(new ClickListener() {

                public void buttonClick(ClickEvent event) {
                    String newName = (String) newNameField.getValue();
                    if (newName != null && !"".equals(newName)) {
                        confirm.closeDialog();

                        renameFolder(folder.getFolderId(), newName);

                        synchronizeAccount(folder.getAccountId(), Controller.get());
                        refresh();
                    } else {
                        Controller.get().showError(Lang.get("please-enter-a-new-folder-name"));
                    }
                }
            });

            Controller.get().getApplication().getMainWindow().addWindow(confirm);
        } else if (Lang.get("delete-folder").equals(action.getCaption())) {
            final ConfirmDialog confirm = new ConfirmDialog(Lang.get("confirm"), Lang.get("delete-folder"),
                    Lang.get("are-you-sure-you-want-to-delete-this-folder"));

            confirm.addConfirmButtonListener(new ClickListener() {

                public void buttonClick(ClickEvent event) {
                    confirm.closeDialog();

                    deleteFolder(folder.getFolderId());

                    synchronizeAccount(folder.getAccountId(), Controller.get());
                    refresh();
                }
            });

            Controller.get().getApplication().getMainWindow().addWindow(confirm);
        }
    }

    /**
     * Refresh the tree contents after a synchronization with the server. No
     * synchronization is performed in this method.
     *
     * The current tree root expansion state and selected folder (if any) are
     * preserved.
     */
    public void refresh() {
        ArrayList<Long> expanded = new ArrayList<Long>();
        for (Object root : rootItemIds()) {
            if (isExpanded(root)) {
                Account account = getFolderContainer().getAccount(root);
                if (account != null) {
                    expanded.add(account.getAccountId());
                }
            }
        }
        Folder selectedFolder = getFolderContainer().getFolder(getValue());

        getFolderContainer().refresh();

        for (Long accountId : expanded) {
            expandItem(getFolderContainer().getAccountItemId(accountId));
        }
        if (selectedFolder != null) {
            Object id = getFolderContainer().getFolderItemId(selectedFolder.getAccountId(),
                    selectedFolder.getFolderId());
            select(id);
        }
    }

    /**
     * Similar to {@link MailManager#addFolder(long, String)}: create a new
     * folder. Success or error message display is handled inside this method.
     */
    private void addFolder(long accountId, String displayName) {
        Controller controller = Controller.get();
        try {
            Mailbox mailbox = MailboxFactoryUtil.getMailbox(controller.getUser().getUserId(), accountId,
                    controller.getPasswordRetriever().getPassword(accountId));

            mailbox.addFolder(displayName);

            controller.showInfo(Lang.get("folder-has-been-created"));
        } catch (MailException me) {
            if (me.getType() == MailException.FOLDER_ALREADY_EXISTS) {
                controller.showError(Lang.get("a-folder-with-the-same-name-already-exists"));
                return;
            }

            _log.error(me, me);

            controller.showError(Lang.get("unable-to-create-folder"));
        } catch (PortalException e) {
            _log.error(e, e);

            controller.showError(Lang.get("unable-to-create-folder"));
        } catch (SystemException e) {
            _log.error(e, e);

            controller.showError(Lang.get("unable-to-create-folder"));
        }

    }

    /**
     * Similar to {@link MailManager#renameFolder(long, String)}: rename a
     * folder. Success or error message display is handled inside this method.
     */
    private void renameFolder(long folderId, String displayName) {
        Controller controller = Controller.get();

        try {
            Folder folder = FolderLocalServiceUtil.getFolder(folderId);

            Mailbox mailbox = MailboxFactoryUtil.getMailbox(controller.getUser().getUserId(), folder.getAccountId(),
                    controller.getPasswordRetriever().getPassword(folder.getAccountId()));

            mailbox.renameFolder(folderId, displayName);

            controller.showInfo(Lang.get("folder-renamed-successfully"));
        } catch (MailException me) {
            if (me.getType() == MailException.FOLDER_ALREADY_EXISTS) {
                controller.showError(Lang.get("a-folder-with-the-same-name-already-exists"));
                return;
            }

            _log.error(me, me);

            controller.showError(Lang.get("unable-to-rename-folder"));
        } catch (PortalException e) {
            _log.error(e, e);

            controller.showError(Lang.get("unable-to-rename-folder"));
        } catch (SystemException e) {
            _log.error(e, e);

            controller.showError(Lang.get("unable-to-rename-folder"));
        }

    }

    /**
     * Similar to {@link MailManager#deleteFolder(long, String)}: delete a
     * folder. Success or error message display is handled inside this method.
     */
    private void deleteFolder(long folderId) {
        Controller controller = Controller.get();

        try {
            Folder folder = FolderLocalServiceUtil.getFolder(folderId);

            Mailbox mailbox = MailboxFactoryUtil.getMailbox(controller.getUser().getUserId(), folder.getAccountId(),
                    controller.getPasswordRetriever().getPassword(folder.getAccountId()));

            mailbox.deleteFolder(folderId);

            controller.showInfo(Lang.get("folder-has-been-deleted"));
        } catch (MailException me) {
            if (me.getType() == MailException.FOLDER_REQUIRED) {
                controller.showError(Lang.get("this-is-a-required-folder-and-can-not-be-deleted"));
                return;
            } else if (me.getType() == MailException.FOLDER_DELETE_FAILED) {
                controller.showError(Lang.get("the-mail-server-will-not-allow-this-folder-to-be-deleted"));
                return;
            }

            _log.error(me, me);

            controller.showError(Lang.get("unable-to-delete-folder"));
        } catch (PortalException e) {
            _log.error(e, e);

            controller.showError(Lang.get("unable-to-delete-folder"));
        } catch (SystemException e) {
            _log.error(e, e);

            controller.showError(Lang.get("unable-to-delete-folder"));
        }

    }

    private void synchronizeAccount(final long accountId, Controller controller) {
        try {
            Account acc = AccountLocalServiceUtil.getAccount(accountId);
            if (acc.isSavePassword()) {
                controller.getMailManager().synchronizeAccount(accountId);
            } else if (controller.getPasswordRetriever().getPassword(accountId) != null) {
                controller.getMailManager().synchronizeAccount(accountId);
            }
        } catch (SystemException e) {
            controller.showError(Lang.get("unable-to-synchronize-account"), e);
        } catch (PortalException e) {
            controller.showError(Lang.get("unable-to-synchronize-account"), e);
        }
    }

    private static Log _log = LogFactoryUtil.getLog(FolderTree.class);

}