org.duracloud.account.app.controller.AccountGroupsController.java Source code

Java tutorial

Introduction

Here is the source code for org.duracloud.account.app.controller.AccountGroupsController.java

Source

/*
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 *     http://duracloud.org/license/
 */
package org.duracloud.account.app.controller;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.duracloud.account.app.controller.GroupsForm.Action;
import org.duracloud.account.db.model.AccountInfo;
import org.duracloud.account.db.model.DuracloudGroup;
import org.duracloud.account.db.model.DuracloudUser;
import org.duracloud.account.db.util.AccountService;
import org.duracloud.account.db.util.DuracloudGroupService;
import org.duracloud.account.db.util.error.DuracloudGroupAlreadyExistsException;
import org.duracloud.account.db.util.error.DuracloudGroupNotFoundException;
import org.duracloud.account.db.util.error.InvalidGroupNameException;
import org.duracloud.common.error.DuraCloudRuntimeException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * 
 * @author Daniel Bernstein Date: Nov 9, 2011
 */
@Controller
@Lazy
public class AccountGroupsController extends AbstractAccountController {

    protected static final String AVAILABLE_USERS_KEY = "availableUsers";
    protected static final String GROUPS_VIEW_ID = "account-groups";
    protected static final String GROUP_VIEW_ID = "account-group";
    protected static final String GROUP_EDIT_VIEW_ID = "account-group-edit";

    protected static final String GROUPS_FORM_KEY = "groupsForm";
    protected static final String GROUP_FORM_KEY = "groupForm";
    protected static String GROUP_USERS_KEY = "groupUsers";
    protected static String GROUP_NAME_KEY = "groupName";
    protected static String GROUP_KEY = "group";

    protected static final String GROUPS_PATH = ACCOUNT_PATH + "/groups";
    protected static final String GROUP_PATH = GROUPS_PATH + "/{groupName:[a-z0-9._\\-@]+}";
    protected static final String GROUP_EDIT_PATH = GROUP_PATH + "/edit";

    private static final String GROUP_NAME_RESERVED_ERROR_CODE = "error.groupName.reserved";
    private static final String GROUP_NAME_INVALID_ERROR_CODE = "error.groupName.invalid";
    private static final String GROUP_NAME_EXISTS_ERROR_CODE = "error.groupName.exists";
    private static final String GROUP_NAME_RESERVED_MESSAGE = "The group name you specified is a reserved name. Please try another.";
    private static final String GROUP_NAME_INVALID_MESSAGE = "Group names can contain only lowercase letters, numbers, '.', '@',"
            + "'-', or '_' and must start and end only with letters or numbers.";
    private static final String GROUP_NAME_EXISTS_MESSAGE = "This group already exists. Please choose another name.";

    @Autowired
    protected DuracloudGroupService duracloudGroupService;

    @RequestMapping(value = GROUPS_PATH, method = RequestMethod.GET)
    public String getGroups(@PathVariable Long accountId, Model model) throws Exception {
        addGroupsObjectsToModel(getAccountService(accountId), model);

        return GROUPS_VIEW_ID;
    }

    @RequestMapping(value = GROUPS_PATH, method = RequestMethod.POST)
    @Transactional
    public String modifyGroups(@PathVariable Long accountId, Model model,
            @ModelAttribute(GROUPS_FORM_KEY) @Valid GroupsForm form, BindingResult result) throws Exception {

        AccountService as = this.accountManagerService.getAccount(accountId);
        GroupsForm.Action action = form.getAction();

        if (action == Action.ADD) {
            String name = form.getGroupName();
            String groupName = DuracloudGroup.PREFIX + name;
            try {
                duracloudGroupService.createGroup(groupName, accountId);

            } catch (InvalidGroupNameException e) {
                if (groupName.equalsIgnoreCase(DuracloudGroup.PUBLIC_GROUP_NAME)) {
                    result.rejectValue(GROUP_NAME_KEY, GROUP_NAME_RESERVED_ERROR_CODE, GROUP_NAME_RESERVED_MESSAGE);

                } else {
                    result.rejectValue(GROUP_NAME_KEY, GROUP_NAME_INVALID_ERROR_CODE, GROUP_NAME_INVALID_MESSAGE);
                }

            } catch (DuracloudGroupAlreadyExistsException e) {
                result.rejectValue(GROUP_NAME_KEY, GROUP_NAME_EXISTS_ERROR_CODE, GROUP_NAME_EXISTS_MESSAGE);
            }

            if (!result.hasFieldErrors()) {
                return formatGroupRedirect(accountId, groupName, "/edit");
            }
        } else {
            String[] groups = form.getGroupNames();
            if (groups != null) {
                for (String name : groups) {
                    DuracloudGroup group = duracloudGroupService.getGroup(name, accountId);
                    removeGroup(group, accountId);
                }
            }
        }

        addGroupsObjectsToModel(as, model);

        return GROUPS_VIEW_ID;
    }

    @RequestMapping(value = GROUP_PATH, method = RequestMethod.GET)
    public String getGroup(@PathVariable Long accountId, @PathVariable String groupName, Model model)
            throws Exception {

        addUserToModel(model);
        model.addAttribute(GROUPS_FORM_KEY, new GroupsForm());
        AccountService as = getAccountService(accountId);
        List<DuracloudGroup> groups = getGroups(accountId);
        DuracloudGroup group = getGroup(groupName, groups);
        addGroupToModel(group, model);

        addGroupsObjectsToModel(as, groups, model);
        return GROUP_VIEW_ID;
    }

    private List<DuracloudGroup> getGroups(Long accountId) {
        Set<DuracloudGroup> set = this.duracloudGroupService.getGroups(accountId);
        List<DuracloudGroup> list = new LinkedList<DuracloudGroup>();
        if (set != null) {
            list.addAll(set);
        }

        return list;
    }

    @RequestMapping(value = GROUP_EDIT_PATH, method = RequestMethod.GET)
    public String editGroup(@PathVariable Long accountId, @PathVariable String groupName,
            HttpServletRequest request, Model model) throws Exception {

        AccountService as = getAccountService(accountId);

        List<DuracloudGroup> groups = getGroups(accountId);
        addGroupsObjectsToModel(as, groups, model);

        DuracloudGroup group = getGroup(groupName, groups);
        addGroupToModel(group, model);

        model.addAttribute(GROUP_FORM_KEY, new GroupForm());
        Set<DuracloudUser> groupUsers = group.getUsers();

        addAvailableUsersToModel(as, groupUsers, model);
        HttpSession session = request.getSession();
        session.removeAttribute(GROUP_USERS_KEY);
        addGroupUsersIfNotAlreadyInSession(group, model, session);
        return GROUP_EDIT_VIEW_ID;
    }

    @RequestMapping(value = GROUP_EDIT_PATH, method = RequestMethod.POST)
    @Transactional
    public String editGroup(@PathVariable Long accountId, @PathVariable String groupName,
            @ModelAttribute(GROUP_FORM_KEY) @Valid GroupForm form, HttpServletRequest request, Model model)
            throws Exception {

        GroupForm.Action action = form.getAction();
        AccountService as = getAccountService(accountId);
        List<DuracloudGroup> groups = getGroups(accountId);
        DuracloudGroup group = getGroup(groupName, groups);
        addGroupToModel(group, model);

        HttpSession session = request.getSession();

        List<DuracloudUser> groupUsers = addGroupUsersIfNotAlreadyInSession(group, model, session);

        // handle save case
        if (action == GroupForm.Action.SAVE) {
            Set<DuracloudUser> users = new HashSet<DuracloudUser>(groupUsers);
            save(group, users, accountId, form);
            session.removeAttribute(GROUP_USERS_KEY);

            return formatGroupRedirect(accountId, groupName, null);

        }

        Collection<DuracloudUser> availableUsers = getAvailableUsers(as, groupUsers);

        if (action == GroupForm.Action.ADD) {
            // handle add
            String[] availableUsernames = form.getAvailableUsernames();
            if (availableUsernames != null) {
                for (String username : availableUsernames) {
                    DuracloudUser user = getUser(username, availableUsers);
                    if (user != null) {
                        groupUsers.add(user);
                    }
                }

                form.setAvailableUsernames(null);
                form.setGroupUsernames(availableUsernames);
            }

        } else if (action == GroupForm.Action.REMOVE) {
            String[] groupUsernames = form.getGroupUsernames();
            if (groupUsernames != null) {
                for (String username : groupUsernames) {
                    DuracloudUser user = getUser(username, groupUsers);
                    if (user != null) {
                        groupUsers.remove(user);
                        availableUsers.add(user);
                    }
                }

                form.setGroupUsernames(null);
                form.setAvailableUsernames(groupUsernames);
            }
        } else {
            throw new DuraCloudRuntimeException("[" + action + "] not supported.");
        }

        model.addAttribute(GROUP_FORM_KEY, form);
        addAvailableUsersToModel(availableUsers, groupUsers, model);
        addGroupsObjectsToModel(as, groups, model);

        return GROUP_EDIT_VIEW_ID;
    }

    private String formatGroupRedirect(Long accountId, String groupName, String suffix) {
        String redirect = "redirect:" + ACCOUNTS_PATH + GROUP_PATH;
        redirect = redirect.replace("{accountId}", String.valueOf(accountId));
        redirect = redirect.replaceAll("\\{groupName.*\\}", String.valueOf(groupName));
        redirect += (suffix != null ? suffix : "");
        return redirect;
    }

    private void addAvailableUsersToModel(Collection<DuracloudUser> allUsers, Collection<DuracloudUser> groupUsers,
            Model model) {
        if (allUsers != null && groupUsers != null) {
            allUsers.removeAll(groupUsers);
        }
        model.addAttribute(AVAILABLE_USERS_KEY, allUsers);
    }

    private DuracloudUser getUser(String username, Collection<DuracloudUser> users) {
        for (DuracloudUser user : users) {
            if (user.getUsername().equals(username)) {
                return user;
            }
        }

        return null;
    }

    private List<DuracloudUser> addGroupUsersIfNotAlreadyInSession(DuracloudGroup group, Model model,
            HttpSession session) {
        List<DuracloudUser> groupUsers = (List<DuracloudUser>) session.getAttribute(GROUP_USERS_KEY);
        if (groupUsers == null) {
            groupUsers = new LinkedList<DuracloudUser>();
            groupUsers.addAll(group.getUsers());
            Collections.sort(groupUsers, USERNAME_COMPARATOR);
            session.setAttribute(GROUP_USERS_KEY, groupUsers);
        }

        model.addAttribute(GROUP_USERS_KEY, groupUsers);

        return groupUsers;
    }

    private void save(DuracloudGroup group, Set<DuracloudUser> groupUsers, Long accountId, GroupForm form)
            throws DuracloudGroupNotFoundException {
        duracloudGroupService.updateGroupUsers(group, groupUsers, accountId);
        form.reset();
    }

    private void removeGroup(DuracloudGroup group, Long accountId) {
        this.duracloudGroupService.deleteGroup(group, accountId);
    }

    private AccountService getAccountService(Long accountId) throws Exception {
        return this.accountManagerService.getAccount(accountId);
    }

    private void addGroupsObjectsToModel(AccountService as, Model model) throws Exception {
        AccountInfo account = as.retrieveAccountInfo();
        Long accountId = account.getId();
        model.addAttribute(ACCOUNT_INFO_KEY, account);
        addGroupsObjectsToModel(as, this.getGroups(accountId), model);
    }

    private void addGroupsObjectsToModel(AccountService as, List<DuracloudGroup> groups, Model model)
            throws Exception {
        addUserToModel(model);
        model.addAttribute(ACCOUNT_INFO_KEY, as.retrieveAccountInfo());
        model.addAttribute("accountId", as.getAccountId());
        if (!model.asMap().containsKey(GROUPS_FORM_KEY)) {
            model.addAttribute(GROUPS_FORM_KEY, new GroupsForm());
        }
        addGroupsToModel(model, groups);
    }

    private void addAvailableUsersToModel(AccountService as, Collection<DuracloudUser> groupUsers, Model model) {
        Collection<DuracloudUser> availableUsers = getAvailableUsers(as, groupUsers);
        addAvailableUsersToModel(availableUsers, groupUsers, model);
    }

    private Collection<DuracloudUser> getAvailableUsers(AccountService as, Collection<DuracloudUser> groupUsers) {
        Set<DuracloudUser> allUsers = as.getUsers();
        LinkedList<DuracloudUser> list = new LinkedList<DuracloudUser>();
        list.addAll(allUsers);
        for (DuracloudUser user : allUsers) {
            if (user.isRoot()) {
                list.remove(user);
            }
        }

        if (groupUsers != null) {
            list.removeAll(groupUsers);
        }

        Collections.sort(list, USERNAME_COMPARATOR);
        return list;
    }

    private static Comparator<DuracloudUser> USERNAME_COMPARATOR = new Comparator<DuracloudUser>() {

        @Override
        public int compare(DuracloudUser o1, DuracloudUser o2) {
            return o1.getUsername().compareTo(o2.getUsername());
        }
    };

    private void addGroupToModel(DuracloudGroup group, Model model) {
        model.addAttribute(GROUP_KEY, group);
        model.addAttribute(GROUP_USERS_KEY, group.getUsers());
    }

    private DuracloudGroup getGroup(String groupName, List<DuracloudGroup> groups)
            throws DuracloudGroupNotFoundException {
        for (DuracloudGroup g : groups) {
            if (g.getName().equalsIgnoreCase(groupName)) {
                return g;
            }
        }

        throw new DuracloudGroupNotFoundException("no group named '" + groupName + "' found in group set.");
    }

    private void addGroupsToModel(Model model, List<DuracloudGroup> groups) {
        model.addAttribute("groups", groups);
    }

    public void setDuracloudGroupService(DuracloudGroupService groupService) {
        this.duracloudGroupService = groupService;

    }

}