/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.persistent.hibernate;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

import gov.va.med.fw.model.AbstractKeyedEntity;
import gov.va.med.fw.persistent.DAOException;

import gov.va.med.esr.common.model.security.ESRRolePrincipalImpl;
import gov.va.med.esr.common.model.security.ESRUserPrincipalImpl;

/**
 * 
 * @author DNS   MANSOG
 * @date Aug 4, 2005 9:54:29 AM
 * @version 1.0
 */
public class UserRoleTest
    extends AbstractKeyedEntityDAOTestCase {
    private static final String QUERY_FIND_BY_USERNAME = "userPrincipal_FindByUserName";
    private static final String QUERY_FIND_BY_ROLENAME = "rolePrincipal_FindByRoleName";
    private static final String PARAM_USER_NAME        = "name";
    private static final String PARAM_ROLE_NAME        = "name";

    private static int          count                  = 0;

    protected DAOTestMode[] setUpTests() {
        return new DAOTestMode[] { TEST_ALL };
    }

    /* (non-Javadoc)
     * @see gov.va.med.esr.common.persistent.hibernate.AbstractKeyedEntityDAOTestCase#setUpTestObject()
     */
    protected AbstractKeyedEntity setUpTestObject() throws Exception {
        ESRUserPrincipalImpl user = buildUserPrincipal();
        user.addUserRole(buildRolePrincipal());
        user.addUserRole(buildRolePrincipal());
        return user;
    }

    /* (non-Javadoc)
     * @see gov.va.med.esr.common.persistent.hibernate.AbstractKeyedEntityDAOTestCase#modifyTestObject(gov.va.med.fw.model.AbstractKeyedEntity)
     */
    protected void modifyTestObject(AbstractKeyedEntity obj) throws Exception {
        ESRUserPrincipalImpl user = (ESRUserPrincipalImpl) obj;

        for (Iterator iter = user.getUserRoles().iterator(); iter.hasNext();) {
            ESRRolePrincipalImpl role = (ESRRolePrincipalImpl) iter.next();
            role.setDescription(role.getName() + " Modified");
        }
    }

    public void testAddUserRole() throws Exception {
        //addUserRole("weblogic", "weblogic", "ROLE_USER", true);
        //addUserRole(findOrCreateUser("esr", "esr"), new ESRRolePrincipalImpl[]{findOrCreateRole("ROLE_USER")}, true);
    }

    /**
     * Test case to add a user if any of the user, role or user role does not exists before.
     * 
     * @throws Exception
     */
    public void testAddUserRoleIfNotExists() throws Exception {
        addUserRoleIfNotExists("weblogic", "weblogic", "ROLE_USER");
        addUserRoleIfNotExists("bea", "bea", "ROLE_USER");
        addUserRoleIfNotExists("esr", "esr", "ROLE_USER");
    }

    private ESRRolePrincipalImpl buildRolePrincipal() {
        String current = "" + System.currentTimeMillis();
        ESRRolePrincipalImpl rp = new ESRRolePrincipalImpl();
        String name = "ROLE_" + current + (count++);
        rp.setName(name);
        rp.setDescription("A " + name + " role");
        return rp;
    }

    private ESRUserPrincipalImpl buildUserPrincipal() {
        ESRUserPrincipalImpl up = new ESRUserPrincipalImpl();
        String current = "" + System.currentTimeMillis();
        String name = "USER_" + current + (count++);
        up.setName(name);
        up.setPassword("welcome");
        up.setPasswordChangeDate(new Date());
        up.setFullName(name + " user");
        return up;
    }

    private void addUserRoleIfNotExists(String userName, String password,
            String roleName) throws Exception {
        ESRUserPrincipalImpl user = findOrCreateUser(userName, password);
        ESRRolePrincipalImpl role = findOrCreateRole(roleName);
        if (user.getUserRoles().contains(role)) {
            System.out.println("User already contains this role");
            return;
        }
        addUserRole(user, new ESRRolePrincipalImpl[] { role }, true);
    }

    private void addRoleToUser(String userName, String password,
            String roleName, boolean commit) throws Exception {
        findOrCreateRole(roleName);
    }

    private void addUserRole(String userName, String password, String roleName,
            boolean commit) throws Exception {
        ESRUserPrincipalImpl up = createUserPrincipal(userName, password);
        up.addUserRole(createRolePrincipal(roleName));
        saveObjectTest(up, commit);
    }

    private ESRUserPrincipalImpl createUserPrincipal(String userName,
            String password) {
        ESRUserPrincipalImpl up = new ESRUserPrincipalImpl(userName);
        up.setPassword(password);
        up.setPasswordChangeDate(new Date());
        up.setFullName(userName);
        return up;
    }

    private ESRRolePrincipalImpl createRolePrincipal(String roleName) {
        ESRRolePrincipalImpl rp = new ESRRolePrincipalImpl(roleName);
        rp.setDescription(roleName);
        return rp;
    }

    private void addUserRole(ESRUserPrincipalImpl user,
            ESRRolePrincipalImpl[] roles, boolean commit) throws Exception {
        if (user != null && roles != null) {
            for (int r = 0; r < roles.length; r++) {
                user.addUserRole(roles[r]);
            }
        }
        saveAndLoadInTransaction(user);
    }

    private void addUserRole() throws Exception {
        ESRRolePrincipalImpl[] roles = { buildRolePrincipal(),
                buildRolePrincipal() };
        addUserRole(buildUserPrincipal(), roles, false);
    }

    /**
     * Find a user with a given name. If no user found, this method create a new ESRUserPrincipalImpl
     * Object. This method simply create a Object, caller is responsible for persistence of this Object.
     * 
     * @param userName
     * @param password
     * @return ESRUserPrincipalImpl
     * @throws DAOException
     */
    protected  ESRUserPrincipalImpl findOrCreateUser(String userName, String password)
            throws DAOException {
        ESRUserPrincipalImpl user = findUserPrincipalByName(userName);
        if (user == null) {
            user = createUserPrincipal(userName, password);
        }
        return user;
    }

    /**
     * Find a role with a given name. If no role found, this method create a new ESRRolePrincipalImpl
     * Object. This method simply create a Object, caller is responsible for persistence of this Object.
     * 
     * @param roleName
     * @return
     * @throws DAOException
     */
    protected ESRRolePrincipalImpl findOrCreateRole(String roleName)
            throws DAOException {
        ESRRolePrincipalImpl role = findRolePrincipalByName(roleName);
        if (role == null) {
            role = createRolePrincipal(roleName);
        }
        return role;
    }

    /**
     * Find the ESRUserPrincipal given a user name.
     * 
     * @param userName
     * @return ESRUserPrincipal
     * @throws DAOException
     */
    protected ESRUserPrincipalImpl findUserPrincipalByName(String userName)
            throws DAOException {
        List list = getDAO().findByNamedQueryAndNamedParam(
                QUERY_FIND_BY_USERNAME, PARAM_USER_NAME, userName);
        if (list != null && list.size() > 0) {
            return (ESRUserPrincipalImpl) list.get(0);
        }
        return null;
    }

    /**
     * Find the ESRRolePrincipal given role name.
     * 
     * @param roleName
     * @return ESRRolePrincipal
     * @throws DAOException
     */
    protected ESRRolePrincipalImpl findRolePrincipalByName(String roleName)
            throws DAOException {
        List list = getDAO().findByNamedQueryAndNamedParam(
                QUERY_FIND_BY_ROLENAME, PARAM_ROLE_NAME, roleName);
        if (list != null && list.size() > 0) {
            return (ESRRolePrincipalImpl) list.get(0);
        }
        return null;
    }
}