eu.scape_project.planning.user.Groups.java Source code

Java tutorial

Introduction

Here is the source code for eu.scape_project.planning.user.Groups.java

Source

/*******************************************************************************
 * Copyright 2006 - 2012 Vienna University of Technology,
 * Department of Software Technology and Interactive Systems, IFS
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package eu.scape_project.planning.user;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;

import javax.annotation.PostConstruct;
import javax.ejb.Stateful;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import eu.scape_project.planning.model.GroupInvitation;
import eu.scape_project.planning.model.User;
import eu.scape_project.planning.model.UserGroup;
import eu.scape_project.planning.utils.ConfigurationLoader;

import org.apache.commons.configuration.Configuration;
import org.slf4j.Logger;

/**
 * Class to update the group of the current user.
 */
@Stateful
@SessionScoped
public class Groups implements Serializable {
    /**
     * Serial version UID.
     */
    private static final long serialVersionUID = 1811189638942547758L;

    @Inject
    private Logger log;

    @Inject
    private EntityManager em;

    @Inject
    private User user;

    @Inject
    private ConfigurationLoader configurationLoader;

    private Configuration config;

    /**
     * Users marked as changed.
     */
    private Set<User> changedUsers = new HashSet<User>();

    /**
     * Groups marked as changed.
     */
    private Set<UserGroup> changedGroups = new HashSet<UserGroup>();

    /**
     * The current users of the group.
     */
    private List<User> groupUsers = new ArrayList<User>();

    /**
     * Initialises the class.
     */
    @PostConstruct
    public void init() {
        config = configurationLoader.load();

        changedUsers.clear();
        changedGroups.clear();

        groupUsers = em.createQuery("SELECT u FROM User u WHERE u.userGroup = :group", User.class)
                .setParameter("group", user.getUserGroup()).getResultList();
    }

    /**
     * Saves changes.
     */
    public void save() {
        em.merge(user);

        // Save changed users
        for (User changedUser : changedUsers) {
            em.merge(changedUser);
        }

        // Save/delete changed groups
        for (UserGroup changedGroup : changedGroups) {
            List<User> users = em.createQuery("SELECT u FROM User u WHERE u.userGroup = :changedGroup", User.class)
                    .setParameter("changedGroup", changedGroup).getResultList();

            if (users.size() == 0) {
                deleteGroup(changedGroup);
            } else {
                em.merge(changedGroup);
            }
        }

        init();

        log.debug("Saved group of user " + user.getUsername());
    }

    /**
     * Discards changes.
     */
    public void discard() {
        User origUser = em.find(User.class, user.getId());
        user.setUserGroup(origUser.getUserGroup());

        init();

        log.debug("Group changes discarted for user " + user.getUsername());
    }

    /**
     * Deletes the provided group from the DB.
     * 
     * @param group
     *            the group to delete
     */
    private void deleteGroup(UserGroup group) {
        List<GroupInvitation> invitations = em
                .createQuery("SELECT i FROM GroupInvitation i WHERE i.invitedGroup = :invitedGroup",
                        GroupInvitation.class)
                .setParameter("invitedGroup", group).getResultList();
        for (GroupInvitation invitation : invitations) {
            invitation.setInvitedGroup(null);
            em.merge(invitation);
        }

        List<User> users = em.createQuery("SELECT u FROM User u WHERE u.userGroup = :changedGroup", User.class)
                .setParameter("changedGroup", group).getResultList();
        for (User user : users) {
            UserGroup newGroup = new UserGroup();
            newGroup.setName(user.getUsername());
            em.merge(user);
        }

        em.remove(em.merge(group));
    }

    /**
     * Removes the current user from his group.
     */
    public void leaveGroup() {
        removeUser(user);
    }

    /**
     * Removes the provided user from the group of the current user.
     */
    public void removeUser(User user) {
        UserGroup group = new UserGroup();
        group.setName(user.getUsername());

        groupUsers.remove(user);

        switchGroup(user, group);
    }

    /**
     * Marks a user as changed.
     * 
     * @param user
     */
    private void markChangedUser(User user) {
        if (!user.equals(this.user) && !changedUsers.contains(user)) {
            changedUsers.add(user);
        }
    }

    /**
     * Switches the group of the provided user to the provided group.
     * 
     * @param user
     *            the user to change
     * @param group
     *            the group to switch to
     */
    private void switchGroup(User user, UserGroup group) {

        markChangedUser(user);
        changedGroups.add(user.getUserGroup());
        user.setUserGroup(group);

        log.debug("Switched user " + user.getUsername() + " to group " + group.getName());
    }

    /**
     * Invites a user to join the group of the current user.
     * 
     * @param inviteUser
     *            the user to invite
     * @param serverString
     *            the server string
     * @throws InvitationMailException
     *             if the invitation mail could not be send
     * @throws AlreadyGroupMemberException
     *             if the user is already a member of the group
     */
    public void inviteUser(User inviteUser, String serverString)
            throws InvitationMailException, AlreadyGroupMemberException {

        if (inviteUser.getUserGroup().getId() == user.getUserGroup().getId()) {
            throw new AlreadyGroupMemberException();
        }

        GroupInvitation invitation = createInvitation(inviteUser.getEmail());
        sendInvitationMail(inviteUser, invitation, serverString);
    }

    /**
     * Invites users with the provided email address to the group of the current
     * user.
     * 
     * @param inviteMail
     *            the email address of the user to invite
     * @param serverString
     *            the server string
     * @return true if the users were invited, false otherwise
     * @throws InvitationMailException
     *             if the invitation mail could not be send
     * @throws AlreadyGroupMemberException
     *             if the user is already a member of the group
     */
    public void inviteUser(String inviteMail, String serverString)
            throws InvitationMailException, AlreadyGroupMemberException {

        String trimmedInviteMail = inviteMail.trim();

        List<User> users = em.createQuery("SELECT u From User u WHERE u.email = :email", User.class)
                .setParameter("email", trimmedInviteMail).getResultList();

        if (users.size() > 0) {
            // Users found
            for (User user : users) {
                inviteUser(user, serverString);
            }
        } else {
            // No user found
            GroupInvitation invitation = createInvitation(trimmedInviteMail);
            sendInvitationMail(invitation, serverString);
        }
    }

    /**
     * Creates a new invitation for the provided email address.
     * 
     * @param inviteMail
     *            the email address of the user to invite
     * @return an invitation
     */
    private GroupInvitation createInvitation(String inviteMail) {

        List<GroupInvitation> existingInvitations = em
                .createQuery(
                        "SELECT i FROM GroupInvitation i WHERE i.email = :email AND i.invitedGroup = :invitedGroup",
                        GroupInvitation.class)
                .setParameter("email", inviteMail).setParameter("invitedGroup", user.getUserGroup())
                .getResultList();

        for (GroupInvitation existingInvitation : existingInvitations) {
            em.remove(existingInvitation);
        }

        GroupInvitation invitation = new GroupInvitation();
        invitation.setEmail(inviteMail);
        invitation.setInvitationActionToken(UUID.randomUUID().toString());
        invitation.setInvitedGroup(user.getUserGroup());

        em.merge(invitation);
        log.debug("Created GroupInvitation for mail " + inviteMail);

        return invitation;
    }

    /**
     * Sends an invitation mail to the user.
     * 
     * @param toUser
     *            the recipient of the mail
     * @param serverString
     *            the server string
     * @return true if the mail was sent successfully, false otherwise
     * @throws InvitationMailException
     *             if the invitation mail could not be send
     */
    private void sendInvitationMail(GroupInvitation invitation, String serverString)
            throws InvitationMailException {
        try {
            Properties props = System.getProperties();

            props.put("mail.smtp.host", config.getString("mail.smtp.host"));
            Session session = Session.getDefaultInstance(props, null);

            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(config.getString("mail.from")));
            message.setRecipient(RecipientType.TO, new InternetAddress(invitation.getEmail()));
            message.setSubject(
                    user.getFullName() + " invited you to join the Plato group " + user.getUserGroup().getName());

            StringBuilder builder = new StringBuilder();
            builder.append("Hello, \n\n");
            builder.append("The Plato user " + user.getFullName() + " has invited you to join the group "
                    + user.getUserGroup().getName() + ".\n\n");
            builder.append(
                    "You do not seem to be a Plato user. If you would like to accept the invitation, please first create an account at http://"
                            + serverString + "/idp/addUser.jsf.\n");
            builder.append(
                    "If you have an account, please log in and use the following link to accept the invitation: \n");
            builder.append("http://" + serverString + "/plato/user/groupInvitation.jsf?uid="
                    + invitation.getInvitationActionToken());
            builder.append("\n\n--\n");
            builder.append("Your Planningsuite team");

            message.setText(builder.toString());
            message.saveChanges();

            Transport.send(message);
            log.debug("Group invitation mail sent successfully to " + invitation.getEmail());

        } catch (MessagingException e) {
            log.error("Error sending group invitation mail to " + invitation.getEmail(), e);
            throw new InvitationMailException(e);
        }
    }

    /**
     * Sends an invitation mail to the user.
     * 
     * @param toUser
     *            the recipient of the mail
     * @param serverString
     *            the server string
     * @return true if the mail was sent successfully, false otherwise
     * @throws InvitationMailException
     *             if the invitation mail could not be send
     */
    private void sendInvitationMail(User toUser, GroupInvitation invitation, String serverString)
            throws InvitationMailException {
        try {
            Properties props = System.getProperties();

            props.put("mail.smtp.host", config.getString("mail.smtp.host"));
            Session session = Session.getDefaultInstance(props, null);

            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(config.getString("mail.from")));
            message.setRecipient(RecipientType.TO, new InternetAddress(invitation.getEmail()));
            message.setSubject(
                    user.getFullName() + " invited you to join the Plato group " + user.getUserGroup().getName());

            StringBuilder builder = new StringBuilder();
            builder.append("Dear " + toUser.getFullName() + ", \n\n");
            builder.append("The Plato user " + user.getFullName() + " has invited you to join the group "
                    + user.getUserGroup().getName() + ".\n");
            builder.append("Please log in and use the following link to accept the invitation: \n");
            builder.append("http://" + serverString + "/plato/user/groupInvitation.jsf?uid="
                    + invitation.getInvitationActionToken());
            builder.append("\n\n--\n");
            builder.append("Your Planningsuite team");

            message.setText(builder.toString());
            message.saveChanges();

            Transport.send(message);
            log.debug("Group invitation mail sent successfully to " + invitation.getEmail());

        } catch (Exception e) {
            log.error("Error sending group invitation mail to " + invitation.getEmail(), e);
            throw new InvitationMailException(e);
        }
    }

    /**
     * Accept a group invitation.
     * 
     * @param invitationActionToken
     *            the invitation action token
     * @return true if the group was changed, false otherwise
     * @throws GroupNotFoundException
     *             if the group could not be found
     * @throws TokenNotFoundException
     *             if the token could not be found
     * @throws AlreadyGroupMemberException
     *             if the user is already a member of the group
     */
    public void acceptInvitation(String invitationActionToken)
            throws GroupNotFoundException, TokenNotFoundException, AlreadyGroupMemberException {

        try {

            GroupInvitation invitation = em.createQuery(
                    "SELECT i FROM GroupInvitation i WHERE i.invitationActionToken = :invitationActionToken",
                    GroupInvitation.class).setParameter("invitationActionToken", invitationActionToken)
                    .getSingleResult();

            em.remove(invitation);

            if (invitation.getInvitedGroup() == null) {
                throw new GroupNotFoundException();
            }

            if (invitation.getInvitedGroup().getId() == user.getUserGroup().getId()) {
                throw new AlreadyGroupMemberException();
            }

            switchGroup(user, invitation.getInvitedGroup());
            save();

            log.info("Invitation to group " + user.getUserGroup().getName() + " accepted by user "
                    + user.getUsername());

        } catch (NoResultException e) {
            log.info("InvitationActionToken for user " + user.getUsername() + " not found.");
            throw new TokenNotFoundException(e);
        }

    }

    /**
     * Declines the group invitation.
     * 
     * @param invitationActionToken
     *            the invitation action token
     * @throws TokenNotFoundException
     *             if the token could not be found
     */
    public void declineInvitation(String invitationActionToken) throws TokenNotFoundException {
        try {

            GroupInvitation invitation = em.createQuery(
                    "SELECT i FROM GroupInvitation i WHERE i.invitationActionToken = :invitationActionToken",
                    GroupInvitation.class).setParameter("invitationActionToken", invitationActionToken)
                    .getSingleResult();

            em.remove(invitation);

            log.info("Invitation to group " + user.getUserGroup().getName() + " declined by user "
                    + user.getUsername());

        } catch (NoResultException e) {
            log.info("InvitationActionToken for user " + user.getUsername() + " not found.");
            throw new TokenNotFoundException(e);
        }
    }

    /**
     * Returns the group name of an invitation identified by the action token.
     * 
     * @param invitationActionToken
     *            the action token
     * @return the name of the associated group
     * @throws TokenNotFoundException
     *             if the token could not be found
     * @throws GroupNotFoundException
     *             if the group does not exist anymore
     */
    public String getInvitationGroupName(String invitationActionToken)
            throws TokenNotFoundException, GroupNotFoundException {

        try {
            GroupInvitation invitation = em.createQuery(
                    "SELECT i FROM GroupInvitation i WHERE i.invitationActionToken = :invitationActionToken",
                    GroupInvitation.class).setParameter("invitationActionToken", invitationActionToken)
                    .getSingleResult();

            if (invitation.getInvitedGroup() == null) {
                throw new GroupNotFoundException();
            }

            return invitation.getInvitedGroup().getName();
        } catch (NoResultException e) {
            log.info("InvitationActionToken for user " + user.getUsername() + " not found.");
            throw new TokenNotFoundException(e);
        }
    }

    /**
     * Gets the users of the provided group.
     * 
     * @param group
     *            the group
     * @return a list of users
     */
    public List<User> getGroupUsers() {
        return groupUsers;
    }

}