com.userweave.pages.configuration.project.userpanel.UserListPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.userweave.pages.configuration.project.userpanel.UserListPanel.java

Source

/*******************************************************************************
 * This file is part of UserWeave.
 *
 *     UserWeave is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     UserWeave 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 Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with UserWeave.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright 2012 User Prompt GmbH | Psychologic IT Expertise
 *******************************************************************************/
package com.userweave.pages.configuration.project.userpanel;

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

import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;

import com.userweave.application.UserWeaveSession;
import com.userweave.components.customModalWindow.CustomModalWindow;
import com.userweave.dao.ProjectUserRoleJoinDao;
import com.userweave.dao.RoleDao;
import com.userweave.dao.StudyDao;
import com.userweave.domain.Project;
import com.userweave.domain.ProjectUserRoleJoin;
import com.userweave.domain.Role;
import com.userweave.domain.StudyState;
import com.userweave.domain.User;
import com.userweave.pages.configuration.ConfigurationPage;

/**
 * Panel to display a list of users and their respective rights
 * in this project. Other users can also write e-mails to and 
 * delete users.
 * 
 * @author opr
 */
public abstract class UserListPanel extends Panel {
    private static final long serialVersionUID = 1L;

    /**
     * Fragment to display a label with the role
     * of a user.
     * 
     * @author opr
     */
    private class LabelFragment extends Fragment {
        private static final long serialVersionUID = 1L;

        /**
         * Default constructor.
         * 
         * @param id
         *       Markup id.
         * @param role
         *       Rolenae to display.
         */
        public LabelFragment(String id, String role) {
            super(id, "labelFragment", UserListPanel.this);

            add(new Label("role", new StringResourceModel(role, UserListPanel.this, null)));
        }
    }

    /**
     * Fragment to display a list choice to change a users
     * role in the given project.
     * Acitve only, when user is project adimin or particiant.
     * 
     * @author opr
     */
    private class ListChoiceFragment extends Fragment {
        private static final long serialVersionUID = 1L;

        /**
         * The selected role for a user.
         */
        private Role role;

        public void setRole(Role role) {
            this.role = role;
        }

        /**
         * Default constructor.
         * 
         * @param id
         *       Markup id.
         * @param roles
         *       List of roles to display in the list choice.
         * @param join
         *       The current join of the given project, the current
         *       proccesed user and his role in the given project.
         * @param user
         *       Current session user.
         */
        public ListChoiceFragment(String id, List<Role> roles, final ProjectUserRoleJoin join, final User user) {
            super(id, "listChoiceFragment", UserListPanel.this);

            setRole(join.getRole());

            Form form = new Form("form");

            add(form);

            final DropDownChoice choices = new DropDownChoice("roleChoice",
                    new PropertyModel(ListChoiceFragment.this, "role"), roles,
                    new LocalizedRoleChoiceRenderer(UserListPanel.this));

            choices.add(new AjaxFormComponentUpdatingBehavior("onchange") {
                private static final long serialVersionUID = 1L;

                @Override
                protected void onUpdate(AjaxRequestTarget target) {
                    // check, if user still has his role.
                    // needed, because change events from 
                    // other users aren't delegated to the 
                    // users session
                    List<Role> userRoles = // userRoles are currently one element lists
                            roleDao.getRolesByUserAndProject(user, join.getProject());

                    if (user.isAdmin() || // super admin can change everything
                    (userRoles != null && !userRoles.isEmpty() && user.hasRole(userRoles.get(0).getRoleName()))) {
                        ProjectUserRoleJoin newJoin = purjDao.createJoin(join.getProject(), join.getUser(), role);

                        purjDao.save(newJoin);

                        purjDao.delete(join);

                        // reload user privileges, if the user changed
                        // his rights.
                        if (join.getUser().equals(user) && !user.isAdmin()) {
                            UserWeaveSession.get().getUser();
                        }

                        onAfterRoleChange(target);
                    } else {
                        error("NOT SAME ROLE ANYMORE!!!");

                        target.addComponent(feedback);
                    }
                }
            });

            form.add(choices);
        }
    }

    /**
     * A choice renderer to translate role names in a 
     * specific locale.
     * 
     * @author opr
     */
    private class LocalizedRoleChoiceRenderer implements IChoiceRenderer {
        private static final long serialVersionUID = 1L;

        /**
         * Parent component reference to find translation
         * of the given object.
         */
        UserListPanel parent;

        /**
         * Default constructor.
         * 
         * @param parent
         *       Parent component to lookup translation.
         */
        public LocalizedRoleChoiceRenderer(UserListPanel parent) {
            this.parent = parent;
        }

        @Override
        public Object getDisplayValue(Object object) {
            StringResourceModel srm = new StringResourceModel(((Role) object).getRoleName(), parent, null);

            return srm.getObject();
        }

        @Override
        public String getIdValue(Object object, int index) {
            return ((Role) object).getRoleName();
        }
    }

    @SpringBean
    private ProjectUserRoleJoinDao purjDao;

    @SpringBean
    private RoleDao roleDao;

    @SpringBean
    private StudyDao studyDao;

    private boolean isDeleted = false;

    private final FeedbackPanel feedback;

    /**
     * Default constructor
     * 
     * @param id
     *       Markup id of component
     * @param projectUserModel
     *       Purj list model
     * @param selectedProject
     *       The current selected project
     */
    public UserListPanel(String id, List<ProjectUserRoleJoin> projectUserList, final Project selectedProject,
            String resourceKey) {
        super(id);

        Label noUserLabel = new Label("noUserLabel", new StringResourceModel(resourceKey, this, null));

        noUserLabel.setVisible(projectUserList == null || projectUserList.isEmpty());

        add(noUserLabel);

        add(new ListView("userList", projectUserList) {
            private static final long serialVersionUID = 1L;

            @Override
            protected void populateItem(final ListItem item) {
                ProjectUserRoleJoin join = (ProjectUserRoleJoin) item.getModelObject();

                User user = join.getUser();

                // display name and email address of user
                String userName = user.getForename() + " " + user.getSurname();

                item.add(new Label("userName", userName));
                //item.add(new Label("userEmail", user.getEmail()));

                // add mailto link
                item.add(new ExternalLink("mailto", "mailto:" + user.getEmail()));

                // flag to indicate if the row in this list contains a
                // user, who has a project admin role.
                final boolean joinEqualsProjectAdmin = join.getRole().getRoleName().equals(Role.PROJECT_ADMIN);

                final List<ProjectUserRoleJoin> projectAdmins = purjDao.getProjectAdmins(selectedProject);

                final CustomModalWindow deleteModal = getDeleteModal("deleteModal", join);

                final CustomModalWindow unableToDeleteUserModal = getUnableToDeleteModal("unableToDeleteModal");

                AjaxLink deleteLink = getDeleteLink(deleteModal, unableToDeleteUserModal, joinEqualsProjectAdmin,
                        projectAdmins.size(), selectedProject);

                item.add(deleteLink);
                item.add(deleteModal);
                item.add(unableToDeleteUserModal);

                // workflow logic
                User currentUser = UserWeaveSession.get().getUser();

                if (currentUser.hasRole(Role.PROJECT_ADMIN)) {
                    /*
                     * A project admin can delete everybody but himself,
                     * if he is the only project admin. Also he can change
                     * everybodies role, except his own, if he is the only 
                     * project admin.
                     */

                    if (!joinEqualsProjectAdmin) {
                        /*
                         * The rendered row is a user, who is not 
                         * a project admin.
                         */
                        item.add(new ListChoiceFragment("roleFragment", roleDao.findAll(), join, currentUser));
                    } else {
                        /*
                         * The rendered row is a user, who is a 
                         * project admin. Ensure, that at least
                         * two admins are there before the active
                         * user change the role of the row user.
                         */
                        if (projectAdmins.size() > 1) {
                            item.add(new ListChoiceFragment("roleFragment", roleDao.findAll(), join, currentUser));
                        } else {
                            /*
                             * there is only one project admin and the
                             * current user can't change his role nor 
                             * delete him from this project.
                             */
                            item.add(new LabelFragment("roleFragment", join.getRole().getRoleName()));

                            deleteLink.setVisible(false);
                        }
                    }
                } else if (currentUser.hasRole(Role.PROJECT_PARTICIPANT) && !joinEqualsProjectAdmin) // <- participant can't change an admin
                {
                    /*
                     * A project participant can change roles of and 
                     * delete guests and other participants.
                     */

                    List<Role> roles = roleDao.findAll();
                    List<Role> newRoles = new ArrayList<Role>(roles.size() - 1);

                    /*
                     *  Populate a list choice with all roles equal 
                     *  or lower to the current users role.
                     */
                    for (Role r : roles) {
                        if (!(r.getRoleName().compareTo(Role.PROJECT_ADMIN) == 0)) {
                            newRoles.add(r);
                        }
                    }

                    // @see: #1313
                    if (join.getUser().equals(currentUser)) {
                        item.add(new ListChoiceFragment("roleFragment", newRoles, join, currentUser));
                    } else {
                        item.add(new LabelFragment("roleFragment", join.getRole().getRoleName()));
                    }
                    // a project participant can only delete
                    // project guests or himself
                    deleteLink.setVisible(
                            //join.getRole().getRoleName().equals(Role.PROJECT_GUEST) || @see: #1313 
                            join.getUser().equals(currentUser));
                } else {
                    item.add(new LabelFragment("roleFragment", join.getRole().getRoleName()));

                    // guests can always delete themselfs
                    deleteLink.setVisible(join.getUser().equals(currentUser));
                }
            }
        });

        feedback = new FeedbackPanel("feedback");

        feedback.setOutputMarkupId(true);

        add(feedback);
    }

    private void addDeleteLinkToRow() {

    }

    private CustomModalWindow getUnableToDeleteModal(String id) {
        final CustomModalWindow unableToDeleteModal = new CustomModalWindow(id);

        unableToDeleteModal.setPageCreator(new ModalWindow.PageCreator() {
            private static final long serialVersionUID = 1L;

            @Override
            public Page createPage() {
                return new UnableToDeleteWebPage(unableToDeleteModal);
            }
        });

        return unableToDeleteModal;
    }

    private CustomModalWindow getDeleteModal(String id, final ProjectUserRoleJoin join) {
        final CustomModalWindow delete = new CustomModalWindow(id);

        delete.setTitle(new StringResourceModel("deleteUser", this, null));

        delete.setPageCreator(new ModalWindow.PageCreator() {
            private static final long serialVersionUID = 1L;

            @Override
            public Page createPage() {
                return new DeleteUserWebPage(join.getUser(), join.getProject(), delete) {
                    @Override
                    protected void onDelete(AjaxRequestTarget target) {
                        deleteUser(join);

                        isDeleted = true;

                        delete.close(target);
                    }
                };
            }
        });

        delete.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClose(AjaxRequestTarget target) {
                if (isDeleted) {
                    if (join.getUser().equals(UserWeaveSession.get().getUser())) {
                        UserWeaveSession.get().setProjectId(null);

                        setResponsePage(ConfigurationPage.class);
                    } else {
                        onAfterDelete(target);
                    }

                    isDeleted = false;
                }
            }
        });

        return delete;
    }

    private AjaxLink getDeleteLink(final ModalWindow deleteModal, final ModalWindow unableToDeleteUserModal,
            final boolean joinEqualsProjectAdmin, final int numberOfProjectAdmins, final Project project) {
        AjaxLink deleteLink = new AjaxLink("delete") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                // A user, who is project admin and the only one
                // who is registered, can't delete himself from
                // the project as long as not all studies are either
                // finished or in init state. See #974
                //            if(joinEqualsProjectAdmin &&
                //               !isAtLeastOneOtherAdminRegistered(project, user) &&
                //               runningStudiesExistsInProject(project))

                // an admin can only be deleted, if either there
                // are other admins or no running studies exist in
                // project.
                if (joinEqualsProjectAdmin && numberOfProjectAdmins <= 1
                        && runningStudiesExistsInProject(project)) {
                    unableToDeleteUserModal.show(target);
                } else {
                    deleteModal.show(target);
                }
            }
        };

        return deleteLink;
    }

    // temporary not in use, because registered is not needed.
    //   private boolean isAtLeastOneOtherAdminRegistered(final Project project, final User user)
    //   {
    //      List<ProjectUserRoleJoin> projectAdmins = 
    //         purjDao.getProjectAdmins(project);
    //      
    //      boolean atLeastOneOtherAdminIsRegistered = false;
    //      
    //      for(ProjectUserRoleJoin projectAdmin : projectAdmins)
    //      {
    //         if(projectAdmin.getUser().isRegistered() && 
    //            !projectAdmin.getUser().equals(user))
    //         {
    //            atLeastOneOtherAdminIsRegistered = true;
    //            break;
    //         }
    //      }
    //      
    //      return atLeastOneOtherAdminIsRegistered;
    //   }

    private void deleteUser(ProjectUserRoleJoin join) {
        purjDao.delete(join);
    }

    private boolean runningStudiesExistsInProject(Project project) {
        return studyDao.findByProjectAndState(project, false, StudyState.RUNNING).size() > 0;
    }

    protected abstract void onAfterDelete(AjaxRequestTarget target);

    protected abstract void onAfterRoleChange(AjaxRequestTarget target);
}