/*
 *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you 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
 *
 *     https://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 org.apache.directory.fortress.core.impl;


import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.apache.directory.fortress.core.*;
import org.apache.directory.fortress.core.SecurityException;
import org.apache.directory.fortress.core.model.AdminRole;
import org.apache.directory.fortress.core.model.OrgUnit;
import org.apache.directory.fortress.core.model.PermObj;
import org.apache.directory.fortress.core.model.Permission;
import org.apache.directory.fortress.core.model.Role;
import org.apache.directory.fortress.core.model.Session;
import org.apache.directory.fortress.core.model.User;
import org.apache.directory.fortress.core.model.UserAdminRole;
import org.apache.directory.fortress.core.util.Config;
import org.apache.directory.fortress.core.util.EncryptUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.directory.fortress.core.util.LogUtil;


/**
 * DelegatedMgrImpl Tester.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
public class DelegatedMgrImplTest extends TestCase
{
    private static final String CLS_NM = DelegatedMgrImplTest.class.getName();
    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );


    public DelegatedMgrImplTest( String name )
    {
        super( name );
    }

    private static Session adminSess = null;


    public void setUp() throws Exception
    {
        super.setUp();
    }


    public void tearDown() throws Exception
    {
        super.tearDown();
    }


    public static Test suitex()
    {
        TestSuite suite = new TestSuite();
        suite.addTest( new DelegatedMgrImplTest( "testRevokePermissionRole" ) );
        suite.addTest( new DelegatedMgrImplTest( "testDeassignAdminUser" ) );
        suite.addTest( new DelegatedMgrImplTest( "testDeleteUser" ) );
        suite.addTest( new DelegatedMgrImplTest( "testDeletePermission" ) );
        suite.addTest( new DelegatedMgrImplTest( "testDeleteRole" ) );
        suite.addTest( new DelegatedMgrImplTest( "testDeleteOrgInheritance" ) );
        suite.addTest( new DelegatedMgrImplTest( "testDeleteOrgUnit" ) );
        suite.addTest( new DelegatedMgrImplTest( "testDeleteAdminUser" ) );
        suite.addTest( new DelegatedMgrImplTest( "testAddAdminUser" ) );
        suite.addTest( new DelegatedMgrImplTest( "testAddOrgUnit" ) );
        suite.addTest( new DelegatedMgrImplTest( "testUpdateOrgUnit" ) );
        suite.addTest( new DelegatedMgrImplTest( "testAddOrgInheritance" ) );
        suite.addTest( new DelegatedMgrImplTest( "testReadOrgUnit" ) );
        suite.addTest( new DelegatedMgrImplTest( "testSearchOrgUnits" ) );
        suite.addTest( new DelegatedMgrImplTest( "testAddRole" ) );
        suite.addTest( new DelegatedMgrImplTest( "testAddUser" ) );
        suite.addTest( new DelegatedMgrImplTest( "testAddPermission" ) );
        suite.addTest( new DelegatedMgrImplTest( "testAssignAdminUser" ) );
        suite.addTest( new DelegatedMgrImplTest( "testGrantPermissionRole" ) );
        suite.addTest( new DelegatedMgrImplTest( "testCheckAccess" ) );
        suite.addTest( new DelegatedMgrImplTest( "testCanAssignUser" ) );
        suite.addTest( new DelegatedMgrImplTest( "testCanDeassignUser" ) );
        suite.addTest( new DelegatedMgrImplTest( "testCanGrantPerm" ) );
        suite.addTest( new DelegatedMgrImplTest( "testCanRevokePerm" ) );

        return suite;
    }

    public static Test suite()
    {
        TestSuite suite = new TestSuite();
        suite.addTest( new DelegatedMgrImplTest( "testCanAssignUser" ) );

        return suite;
    }

    public void testAddAdminUser()
    {
        // These fortress delegated admin policies are needed for junit test but may have been created by an ant script so won't need to be created here:
        if(loadAdminRequired( "LOAD-ADMIN AROLES_SUPER", AdminRoleTestData.AROLES_SUPER ))
        {
            addOrgUnit( "ADD ORG_PRM_APP0", OrgUnitTestData.ORGS_PRM_APP0[0] );
            addOrgUnit( "ADD ORG_USR_DEV0", OrgUnitTestData.ORGS_USR_DEV0[0] );

            addAdminRoles( "ADD-ARLS SUPER", AdminRoleTestData.AROLES_SUPER, false );
            AdminMgrImplTest.addPermObjs( "ADD-OBS PSWDMGR_OBJ", PermTestData.PSWDMGR_OBJ, false, false );
            AdminMgrImplTest.addPermObjs( "ADD-OBS ADMINMGR_OBJ", PermTestData.ADMINMGR_OBJ, false, false );
            AdminMgrImplTest.addPermObjs( "ADD-OBS DELEGATEDMGR_OBJ", PermTestData.DELEGATEDMGR_OBJ, false, false );
            AdminMgrImplTest.addPermObjs( "ADD-OBS DELEGATEDREVIEWMGR_OBJ", PermTestData.DELEGATEDREVIEWMGR_OBJ, false,
                false );
            AdminMgrImplTest.addPermObjs( "ADD-OBS REVIEWMGR_OBJ", PermTestData.REVIEWMGR_OBJ, false, false );
            AdminMgrImplTest.addPermObjs( "ADD-OBS GROUPMGR_OBJ", PermTestData.GROUPMGR_OBJ, false, false );

            AdminMgrImplTest.addPermOps( "ADD-OPS GROUPMGR_OBJ GROUPMGR_OPS", PermTestData.GROUPMGR_OBJ,
                    PermTestData.GROUPMGR_OPS, false, false );
            AdminMgrImplTest.addRoleGrants( "GRNT-APRMS SUPER GRPMGR_OBJ GRPMGR_OPS",
                    AdminRoleTestData.AROLES_SUPER, PermTestData.GROUPMGR_OBJ, PermTestData.GROUPMGR_OPS, false, false );

            AdminMgrImplTest.addPermOps( "ADD-OPS PSWDMGR_OBJ PSWDMGR_OPS", PermTestData.PSWDMGR_OBJ,
                PermTestData.PSWDMGR_OPS, false, false );
            AdminMgrImplTest.addPermOps( "ADD-OPS ADMINMGR_OBJ ADMINMGR_OPS", PermTestData.ADMINMGR_OBJ,
                PermTestData.ADMINMGR_OPS, false, false );
            AdminMgrImplTest.addPermOps( "ADD-OPS DELEGATEDMGR_OBJ DELEGATEDMGR_OPS", PermTestData.DELEGATEDMGR_OBJ,
                PermTestData.DELEGATEDMGR_OPS, false, false );
            AdminMgrImplTest.addPermOps( "ADD-OPS DELEGATEDREVIEWMGR_OBJ DELEGATEDREVIEWMGR_OPS",
                PermTestData.DELEGATEDREVIEWMGR_OBJ, PermTestData.DELEGATEDREVIEWMGR_OPS, false, false );
            AdminMgrImplTest.addPermOps( "ADD-OPS REVIEWMGR_OBJ REVIEWMGR_OPS", PermTestData.REVIEWMGR_OBJ,
                PermTestData.REVIEWMGR_OPS, false, false );
            AdminMgrImplTest.addRoleGrants( "GRNT-APRMS SUPER PSWDMGR_OBJ PSWDMGR_OPS", AdminRoleTestData.AROLES_SUPER,
                PermTestData.PSWDMGR_OBJ, PermTestData.PSWDMGR_OPS, false, false );
            AdminMgrImplTest.addRoleGrants( "GRNT-APRMS SUPER ADMINMGR_OBJ ADMINMGR_OPS", AdminRoleTestData.AROLES_SUPER,
                PermTestData.ADMINMGR_OBJ, PermTestData.ADMINMGR_OPS, false, false );
            AdminMgrImplTest.addRoleGrants( "GRNT-APRMS SUPER DELEGATEDMGR_OBJ DELEGATEDMGR_OPS",
                AdminRoleTestData.AROLES_SUPER, PermTestData.DELEGATEDMGR_OBJ, PermTestData.DELEGATEDMGR_OPS, false, false );
            AdminMgrImplTest.addRoleGrants( "GRNT-APRMS SUPER DELEGATEDREVIEWMGR_OBJ DELEGATEDREVIEWMGR_OPS",
                AdminRoleTestData.AROLES_SUPER, PermTestData.DELEGATEDREVIEWMGR_OBJ, PermTestData.DELEGATEDREVIEWMGR_OPS,
                false, false );
            AdminMgrImplTest.addRoleGrants( "GRNT-APRMS SUPER REVIEWMGR_OBJ REVIEWMGR_OPS", AdminRoleTestData.AROLES_SUPER,
                PermTestData.REVIEWMGR_OBJ, PermTestData.REVIEWMGR_OPS, false, false );
            AdminMgrImplTest.addPermObjs( "ADD-OBS AUDITMGR_OBJ", PermTestData.AUDITMGR_OBJ, false, true );
            AdminMgrImplTest.addPermOps( "ADD-OPS AUDITMGR_OBJ AUDITMGR_OPS", PermTestData.AUDITMGR_OBJ,
                PermTestData.AUDITMGR_OPS, false, true );
            AdminMgrImplTest.addRoleGrants( "GRNT-APRMS SUPER AUDITMGR_OBJ AUDITMGR_OPS", AdminRoleTestData.AROLES_SUPER,
                PermTestData.AUDITMGR_OBJ, PermTestData.AUDITMGR_OPS, false, true );
        }

        PswdPolicyMgrImplTest.add( "ADD " + TestUtils.getDataLabel( PolicyTestData.class, "POLICIES_BASE" ), PolicyTestData.POLICIES_BASE, true );
        AdminMgrImplTest.addUsers( "ADD-USRS TU0", UserTestData.USERS_TU0, false );
        assignAdminUsers( "ASGN-USRS TU0 SUPER", UserTestData.USERS_TU0, AdminRoleTestData.AROLES_SUPER, false );
    }

    private static boolean loadAdminRequired( String msg, String[][] rArray )
    {
        // default return is 'true':
        boolean loadAdmin = true;
        String methodName = ".loadAdminRequired";
        LogUtil.logIt( msg );
        try
        {
            DelReviewMgr dReviewMgr = getDelegatedReviewMgr();
            for ( String[] rle : rArray )
            {
                AdminRole entity = dReviewMgr.readRole( new AdminRole( RoleTestData.getName( rle ) ) );
                if(entity == null)
                {
                    break;
                }
                //AdminRoleTestData.assertEquals( entity, rle );
            }
            // if we get to here it means that admin role has already been loaded
            loadAdmin = false;
        }
        catch ( SecurityException ex )
        {
            // This is the expected when teardown is not required:
            if ( ex.getErrorId() == GlobalErrIds.ROLE_NOT_FOUND )
            {
                // did not find so need to load admin roles
            }
            else
            {
                // Something unexpected occurred here, Report as warning to the logger:
                String warning = methodName + " caught SecurityException=" + ex.getMessage();
                LOG.warn( warning );
                // TODO: Determine if it would be better to throw a SecurityException here.
            }
        }
        LOG.info( methodName + ":" + loadAdmin );
        return loadAdmin;
    }


    public void testDeleteAdminUser()
    {
        deassignAdminUsers( "DEASGN-USRS TU0 SUPER", UserTestData.USERS_TU0, AdminRoleTestData.AROLES_SUPER, false );
        AdminMgrImplTest.deleteUsers( "DEL-USRS TU0", UserTestData.USERS_TU0, true, false );
        AdminMgrImplTest.delRoleGrants( "REVK-APRMS SUPER AUDITMGR_OBJ AUDITMGR_OPS", AdminRoleTestData.AROLES_SUPER,
            PermTestData.AUDITMGR_OBJ, PermTestData.AUDITMGR_OPS, false );
        AdminMgrImplTest.delRoleGrants( "REVK-APRMS SUPER REVIEWMGR_OBJ REVIEWMGR_OPS", AdminRoleTestData.AROLES_SUPER,
            PermTestData.REVIEWMGR_OBJ, PermTestData.REVIEWMGR_OPS, false );
        AdminMgrImplTest.delRoleGrants( "REVK-APRMS SUPER PSWDMGR_OBJ PSWDMGR_OPS", AdminRoleTestData.AROLES_SUPER,
            PermTestData.PSWDMGR_OBJ, PermTestData.PSWDMGR_OPS, false );
        AdminMgrImplTest.delRoleGrants( "REVK-APRMS SUPER ADMINMGR_OBJ ADMINMGR_OPS", AdminRoleTestData.AROLES_SUPER,
            PermTestData.ADMINMGR_OBJ, PermTestData.ADMINMGR_OPS, false );
        AdminMgrImplTest.delRoleGrants( "REVK-APRMS SUPER DELEGATEDREVIEWMGR_OBJ DELEGATEDREVIEWMGR_OPS",
            AdminRoleTestData.AROLES_SUPER, PermTestData.DELEGATEDREVIEWMGR_OBJ, PermTestData.DELEGATEDREVIEWMGR_OPS,
            false );
        AdminMgrImplTest.delRoleGrants( "REVK-APRMS SUPER DELEGATEDMGR_OBJ DELEGATEDMGR_OPS",
            AdminRoleTestData.AROLES_SUPER, PermTestData.DELEGATEDMGR_OBJ, PermTestData.DELEGATEDMGR_OPS, false );
        AdminMgrImplTest.delPermOps( "DEL-OPS AUDITMGR_OBJ AUDITMGR_OPS ", PermTestData.AUDITMGR_OBJ,
            PermTestData.AUDITMGR_OPS, false, false );
        AdminMgrImplTest.delPermOps( "DEL-OPS REVIEWMGR_OBJ REVIEWMGR_OPS ", PermTestData.REVIEWMGR_OBJ,
            PermTestData.REVIEWMGR_OPS, false, false );
        AdminMgrImplTest.delPermOps( "DEL-OPS PSWDMGR_OBJ PSWDMGR_OPS", PermTestData.PSWDMGR_OBJ,
            PermTestData.PSWDMGR_OPS, false, false );
        AdminMgrImplTest.delPermOps( "DEL-OPS ADMINMGR_OBJ ADMINMGR_OPS ", PermTestData.ADMINMGR_OBJ,
            PermTestData.ADMINMGR_OPS, false, false );
        AdminMgrImplTest.delPermOps( "DEL-OPS DELEGATEDREVIEWMGR_OBJ DELEGATEDREVIEWMGR_OPS ",
            PermTestData.DELEGATEDREVIEWMGR_OBJ, PermTestData.DELEGATEDREVIEWMGR_OPS, false, false );
        AdminMgrImplTest.delPermOps( "DEL-OPS DELEGATEDMGR_OBJ DELEGATEDMGR_OPS ", PermTestData.DELEGATEDMGR_OBJ,
            PermTestData.DELEGATEDMGR_OPS, false, false );
        AdminMgrImplTest.delPermObjs( "DEL-OBJS AUDITMGR_OBJ", PermTestData.AUDITMGR_OBJ, false );
        AdminMgrImplTest.delPermObjs( "DEL-OBJS REVIEWMGR_OBJ", PermTestData.REVIEWMGR_OBJ, false );
        AdminMgrImplTest.delPermObjs( "DEL-OBJS PSWDMGR_OBJ", PermTestData.PSWDMGR_OBJ, false );
        AdminMgrImplTest.delPermObjs( "DEL-OBJS ADMINMGR_OBJ", PermTestData.ADMINMGR_OBJ, false );
        AdminMgrImplTest.delPermObjs( "DEL-OBJS DELEGATEDREVIEWMGR_OBJ", PermTestData.DELEGATEDREVIEWMGR_OBJ, false );
        AdminMgrImplTest.delPermObjs( "DEL-OBJS DELEGATEDMGR_OBJ", PermTestData.DELEGATEDMGR_OBJ, false );
        deleteAdminRoles( "DEL-ARLS SUPER", AdminRoleTestData.AROLES_SUPER, false );
        deleteOrgUnit( "DEL ORG_USR_DEV0", OrgUnitTestData.ORGS_USR_DEV0[0] );
        deleteOrgUnit( "DEL ORG_PRM_APP0", OrgUnitTestData.ORGS_PRM_APP0[0] );
    }


    public void testAssignAdminUser()
    {
        //     public void assignUser(User user, Role role)
        assignAdminUsers( "ASGN-USRS TU16 TR1", UserTestData.USERS_TU16_ARBAC, AdminRoleTestData.AROLES_TR1, true );
        assignAdminUserRole( "ASGN-USR TU17A TR2", UserTestData.USERS_TU17A_ARBAC, AdminRoleTestData.AROLES_TR2, true );
    }


    /**
     * 
     * @param msg
     * @param uArray
     * @param rArray
     */
    public static void assignAdminUsers( String msg, String[][] uArray, String[][] rArray, boolean isAdmin )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr;
            DelReviewMgr dReviewMgr;
            if ( isAdmin )
            {
                dAdminMgr = getManagedDelegatedMgr();
                dReviewMgr = getManagedDelegatedReviewMgr();
            }
            else
            {
                dAdminMgr = DelAdminMgrFactory.createInstance( TestUtils.getContext() );
                dReviewMgr = DelReviewMgrFactory.createInstance( TestUtils.getContext() );
            }

            int i = 0;
            for ( String[] usr : uArray )
            {
                i++;
                for ( String[] rle : rArray )
                {
                    UserAdminRole uAdminRole = new UserAdminRole( UserTestData.getUserId( usr ), AdminRoleTestData
                        .getRole( rle ).getName() );
                    dAdminMgr.assignUser( uAdminRole );
                    LOG.debug( "assignAdminUsers user [" + uAdminRole.getUserId() + "] role ["
                        + uAdminRole.getName() + "] successful" );
                    // Let's double check the number of users not associated with role:
                    // This one retrieves the collection of all "roleOccupant" attributes associated with the role node:
                    List<User> users = dReviewMgr.assignedUsers( AdminRoleTestData.getRole( rle ) );
                    assertNotNull( users );
                    assertTrue( CLS_NM + "assignAdminUsers list size check", i == users.size() );
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "assignAdminUsers caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testDeassignAdminUser()
    {
        //     public void deassignUser(User user, Role role)
        deassignAdminUsers( "DEASGN-USRS TU16 TR1", UserTestData.USERS_TU16_ARBAC, AdminRoleTestData.AROLES_TR1, true );
        deassignAdminUserRole( "DEASGN-USR TU17A TR2", UserTestData.USERS_TU17A_ARBAC, AdminRoleTestData.AROLES_TR2,
            true );
    }


    /**
     * @param msg
     * @param uArray
     * @param rArray
     */
    void deassignAdminUsers( String msg, String[][] uArray, String[][] rArray, boolean isAdmin )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr;
            DelReviewMgr dReviewMgr;
            if ( isAdmin )
            {
                dAdminMgr = getManagedDelegatedMgr();
                dReviewMgr = getManagedDelegatedReviewMgr();
            }
            else
            {
                dAdminMgr = DelAdminMgrFactory.createInstance( TestUtils.getContext() );
                dReviewMgr = DelReviewMgrFactory.createInstance( TestUtils.getContext() );
            }
            int i = 0;
            for ( String[] usr : uArray )
            {
                i++;
                for ( String[] rle : rArray )
                {
                    UserAdminRole uAdminRole = new UserAdminRole( UserTestData.getUserId( usr ), AdminRoleTestData
                        .getRole( rle ).getName() );
                    AdminRoleTestData.getRole( rle );
                    dAdminMgr.deassignUser( uAdminRole );
                    LOG.debug( "deassignAdminUsers user [" + uAdminRole.getUserId() + "] role ["
                        + uAdminRole.getName() + "] successful" );
                    // Let's double check the number of users associated with role:
                    List<User> users = dReviewMgr.assignedUsers( AdminRoleTestData.getRole( rle ) );
                    assertNotNull( users );

                    // If this is the last user deassigned from role, both lists will be returned empty:
                    if ( i == uArray.length )
                    {
                        assertTrue( users.size() == 0 );
                    }
                    else
                    {
                        assertTrue( CLS_NM + "deassignAdminUsers list size check",
                            ( rArray.length - i ) == users.size() );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "deassignAdminUsers caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public static void assignAdminUserRole( String msg, String[][] uArray, String[][] rArray, boolean isAdmin )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr;
            if ( isAdmin )
            {
                dAdminMgr = getManagedDelegatedMgr();
            }
            else
            {
                dAdminMgr = DelAdminMgrFactory.createInstance( TestUtils.getContext() );
            }
            int i = 0;
            for ( String[] usr : uArray )
            {
                UserAdminRole uAdminRole = new UserAdminRole( UserTestData.getUserId( usr ), AdminRoleTestData.getRole(
                    rArray[i] ).getName() );
                dAdminMgr.assignUser( uAdminRole );
                i++;
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "assignAdminUsers caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    void deassignAdminUserRole( String msg, String[][] uArray, String[][] rArray, boolean isAdmin )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr;
            if ( isAdmin )
            {
                dAdminMgr = getManagedDelegatedMgr();
            }
            else
            {
                dAdminMgr = DelAdminMgrFactory.createInstance( TestUtils.getContext() );
            }
            int i = 0;
            for ( String[] usr : uArray )
            {
                UserAdminRole uAdminRole = new UserAdminRole( UserTestData.getUserId( usr ), AdminRoleTestData.getRole(
                    rArray[i] ).getName() );
                dAdminMgr.deassignUser( uAdminRole );
                i++;
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "deassignAdminUserRole caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddUser()
    {
        //     public User addUser(User user)
        // the admin user must be added before the "addUsers" can be called:
        //AdminMgrImplTest.addAdminUser("ADD-USRS TU0", UserTestData.USERS_TU0[0]);
        AdminMgrImplTest.addUsers( "ADD-USRS TU16_ARBAC", UserTestData.USERS_TU16_ARBAC, true );
        AdminMgrImplTest.addUsers( "ADD-USRS TU16B_ARBAC", UserTestData.USERS_TU16B_ARBAC, true );
        AdminMgrImplTest.addUsers( "ADD-USRS TU16A_ARBAC", UserTestData.USERS_TU17A_ARBAC, true );
        AdminMgrImplTest.addUsers( "ADD-USRS TU16U_ARBAC", UserTestData.USERS_TU17U_ARBAC, true );

    }


    public void testDeleteUser()
    {
        //     public void disableUser(User user)
        AdminMgrImplTest.deleteUsers( "DEL-USRS TU16B_ARBAC", UserTestData.USERS_TU16B_ARBAC, true, true );
        AdminMgrImplTest.deleteUsers( "DEL-USRS TU16_ARBAC", UserTestData.USERS_TU16_ARBAC, true, true );
        AdminMgrImplTest.deleteUsers( "DEL-USRS TU16A_ARBAC", UserTestData.USERS_TU17A_ARBAC, true, true );
        AdminMgrImplTest.deleteUsers( "DEL-USRS TU16U_ARBAC", UserTestData.USERS_TU17U_ARBAC, true, true );
    }


    public void testAddPermission()
    {
        //     public Permission addPermObj(Permission pOp)
        AdminMgrImplTest.addPermObjs( "ADD-OBS TOB5", PermTestData.OBJS_TOB5, true, false );
        AdminMgrImplTest.addPermObjs( "ADD-OBS ARBAC1", PermTestData.ARBAC_OBJS_1, true, false );
        AdminMgrImplTest
            .addPermOps( "ADD-OPS ARBAC1", PermTestData.ARBAC_OBJS_1, PermTestData.ARBAC_OPS_1, true, false );
        AdminMgrImplTest.addPermObjs( "ADD-OBS ARBAC2", PermTestData.ARBAC_OBJ2, true, false );
        AdminMgrImplTest.addPermOps( "ADD-OPS ARBAC2", PermTestData.ARBAC_OBJ2, PermTestData.ARBAC_OPS_2, true, false );
    }


    public void testDeletePermission()
    {
        //     public void deletePermission(Permission pOp)
        AdminMgrImplTest.delPermObjs( "DEL-OBJS TOB5", PermTestData.OBJS_TOB5, true );
        AdminMgrImplTest
            .delPermOps( "DEL-OPS ARBAC1", PermTestData.ARBAC_OBJS_1, PermTestData.ARBAC_OPS_1, true, false );
        AdminMgrImplTest.delPermObjs( "DEL-OBJS ARBAC1", PermTestData.ARBAC_OBJS_1, true );
        AdminMgrImplTest.delPermOps( "DEL-OPS ARBAC2", PermTestData.ARBAC_OBJ2, PermTestData.ARBAC_OPS_2, true, false );
        AdminMgrImplTest.delPermObjs( "DEL-OBS ARBAC2", PermTestData.ARBAC_OBJ2, true );
    }


    public void testGrantPermissionRole()
    {
        //     public void grantPermission(Permission pOp, Role role)
        AdminMgrImplTest.addRoleGrants( "GRNT-APRMS ARTR2 AROBJ1 AROPS1", AdminRoleTestData.AROLES_TR2,
            PermTestData.ARBAC_OBJS_1, PermTestData.ARBAC_OPS_1, true, false );
    }


    public void testRevokePermissionRole()
    {
        //     public void revokePermission(Permission pOp, Role role)
        AdminMgrImplTest.delRoleGrants( "REVK-APRMS ARTR2 AROBJ1 AROPS1", AdminRoleTestData.AROLES_TR2,
            PermTestData.ARBAC_OBJS_1, PermTestData.ARBAC_OPS_1, true );
    }


    public void testCheckAccess()
    {
        // public boolean checkAccess(String object, String operation, Session session)
        checkAccess( "CHCK-ACS TU1_UPD TO1 TOP1 ", UserTestData.USERS_TU17A_ARBAC, PermTestData.ARBAC_OBJS_1,
            PermTestData.ARBAC_OPS_1, PermTestData.ARBAC_OBJ2, PermTestData.ARBAC_OPS_2 );
    }


    public static void checkAccess( String msg, String[][] uArray, String[][] oArray, String[][] opArray,
        String[][] oArrayBad, String[][] opArrayBad )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAccessMgr dAccessMgr = DelAccessMgrFactory.createInstance( TestUtils.getContext() );
            AccessMgr accessMgr = ( AccessMgr ) dAccessMgr;
            for ( String[] usr : uArray )
            {
                User user = UserTestData.getUser( usr );
                Session session = accessMgr.createSession( user, false );

                assertNotNull( session );
                int i = 0;
                for ( String[] obj : oArray )
                {
                    int j = 0;
                    for ( String[] op : opArray )
                    {
                        // Call checkAccess method
                        assertTrue(
                            CLS_NM + ".checkAccess failed userId [" + user.getUserId() + "] Perm objName ["
                                + PermTestData.getName( obj ) + "] operationName [" + PermTestData.getName( op ) + "]",
                            dAccessMgr.checkAccess( session,
                                new Permission( PermTestData.getName( obj ), PermTestData.getName( op ) ) ) );
                        j++;
                    }
                    i++;
                }
                i = 0;
                for ( String[] obj : oArrayBad )
                {
                    int j = 0;
                    for ( String[] op : opArrayBad )
                    {
                        // Call checkAccess method (this should fail):
                        try
                        {
                            boolean result = dAccessMgr.checkAccess( session, new Permission( PermTestData.getName( oArrayBad[i] ),
                                PermTestData.getName( opArrayBad[j] ) ) );
                            assertTrue(
                                CLS_NM + ".checkAccess failed userId [" + user.getUserId() + "] Perm objName ["
                                    + PermTestData.getName( oArrayBad[i] ) + "] operationName ["
                                    + PermTestData.getName( opArrayBad[j] ) + "]",
                                !result );
                        }
                        catch (SecurityException se)
                        {
                            // The expected condition is security exception perm not exist:
                            assertTrue( CLS_NM + ".checkAccess failed userId [" + user.getUserId() + "] Perm objName ["
                                + PermTestData.getName( oArrayBad[i] ) + "] operationName ["
                                + PermTestData.getName( opArrayBad[j] ) + "], negative use case, incorrect exception id=" + se.getErrorId(), se.getErrorId() == GlobalErrIds.PERM_NOT_EXIST );
                        }
                        j++;
                    }
                    i++;
                }
            }
            LOG.debug( "checkAccess successful" );
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "checkAccess: caught SecurityException rc=" + ex.getErrorId() + ", msg: " + ex.getMessage(),
                ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddRole()
    {
        //     public Role setRole(Role role)
        AdminMgrImplTest.addRoles( "ADD-RLS ROLES_TR14_ARBAC", RoleTestData.ROLES_TR14_ARBAC );
        AdminMgrImplTest.addInheritedRoles( "ADD-INHERIT-RLS ROLES_TR14_ARBAC", RoleTestData.ROLES_TR14_ARBAC );
        AdminMgrImplTest.addRoles( "ADD-RLS ROLES_TR15_ARBAC", RoleTestData.ROLES_TR15_ARBAC );
        AdminMgrImplTest.addInheritedRoles( "ADD-INHERIT-RLS ROLES_TR15_ARBAC", RoleTestData.ROLES_TR15_ARBAC );
        addAdminRoles( "ADD-ADMRLS TR1", AdminRoleTestData.AROLES_TR1, true );
        addAdminRoles( "ADD-ADMRLS TR2", AdminRoleTestData.AROLES_TR2, true );
        addAdminRoles( "ADD-ADMRLS TR3", AdminRoleTestData.AROLES_TR3, true );
        addAdminRoles( "ADD-ADMRLS TR6", AdminRoleTestData.AROLES_TR6_HIER, true );
    }


    /**
     * @param rArray
     */
    public static void addAdminRoles( String msg, String[][] rArray, boolean isAdmin )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr;
            if ( isAdmin )
            {
                dAdminMgr = getManagedDelegatedMgr();
            }
            else
            {
                dAdminMgr = DelAdminMgrFactory.createInstance( TestUtils.getContext() );
            }
            for ( String[] rle : rArray )
            {
                AdminRole role = AdminRoleTestData.getRole( rle );
                AdminRole entity = dAdminMgr.addRole( role );
                LOG.debug( "addAdminRoles role [" + entity.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "addAdminRoles caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(),
                ex );
            fail( ex.getMessage() );
        }
    }


    public void testDeleteRole()
    {
        //     public void deleteRole(Role role)
        deleteAdminRoles( "DEL-ADMRLS TR1", AdminRoleTestData.AROLES_TR1, true );
        deleteAdminRoles( "DEL-ADMRLS TR2", AdminRoleTestData.AROLES_TR2, true );
        deleteAdminRoles( "DEL-ADMRLS TR3", AdminRoleTestData.AROLES_TR3, true );
        deleteAdminRoles( "DEL-ADMRLS TR6", AdminRoleTestData.AROLES_TR6_HIER, true );
        AdminMgrImplTest.deleteInheritedRoles( "DEL-INHERIT-RLS ROLES_TR14_ARBAC", RoleTestData.ROLES_TR14_ARBAC );
        AdminMgrImplTest.deleteRoles( "DEL-RLS ROLES_TR14_ARBAC", RoleTestData.ROLES_TR14_ARBAC );
        AdminMgrImplTest.deleteInheritedRoles( "DEL-INHERIT-RLS ROLES_TR15_ARBAC", RoleTestData.ROLES_TR15_ARBAC );
        AdminMgrImplTest.deleteRoles( "DEL-RLS ROLES_TR15_ARBAC", RoleTestData.ROLES_TR15_ARBAC );
    }


    /**
     * @param rArray
     */
    private void deleteAdminRoles( String msg, String[][] rArray, boolean isAdmin )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr;
            if ( isAdmin )
            {
                dAdminMgr = getManagedDelegatedMgr();
            }
            else
            {
                dAdminMgr = DelAdminMgrFactory.createInstance( TestUtils.getContext() );
            }
            for ( String[] rle : rArray )
            {
                AdminRole role = new AdminRole();
                role.setName( RoleTestData.getName( rle ) );
                dAdminMgr.deleteRole( role );
                LOG.debug( "deleteAdminRoles role [" + role.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "deleteAdminRoles caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testUpdateAdminRole()
    {
        //     public Role updateRole(Role role)
        updateAdminRoles( "UPD-ADMRLS TR3_UPD", AdminRoleTestData.AROLES_TR3_UPD, true );
    }


    /**
     * @param msg
     * @param rArray
     */
    public static void updateAdminRoles( String msg, String[][] rArray, boolean isAdmin )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr;
            if ( isAdmin )
            {
                dAdminMgr = getManagedDelegatedMgr();
            }
            else
            {
                dAdminMgr = DelAdminMgrFactory.createInstance( TestUtils.getContext() );
            }
            for ( String[] rle : rArray )
            {
                AdminRole role = AdminRoleTestData.getRole( rle );
                AdminRole entity = dAdminMgr.updateRole( role );
                LOG.debug( "updateAdminRoles role [" + entity.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "updateAdminRoles caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }

    public enum ASSIGN_OP
    {
        ASSIGN, DEASSIGN
    }


    public void testCanAssignUser()
    {
        //canAssignUsers("CAN-ASGN-USRS TU1 TR1", UserTestData.USERS_TU16_ARBAC, UserTestData.USERS_TU16B_ARBAC, RoleTestData.ROLES_TR14_ARBAC);
        canAssignUsers( "CAN-ASGN-USRS URA_T1 TU17A TU17U TR15", ASSIGN_OP.ASSIGN, URATestData.URA_T1,
            UserTestData.USERS_TU17A_ARBAC, UserTestData.USERS_TU17U_ARBAC, RoleTestData.ROLES_TR15_ARBAC );
    }


    public void testCanDeassignUser()
    {
        canAssignUsers( "CAN-DEASGN-USRS URA_T1 TU17A TU17U TR15", ASSIGN_OP.DEASSIGN, URATestData.URA_T1,
            UserTestData.USERS_TU17A_ARBAC, UserTestData.USERS_TU17U_ARBAC, RoleTestData.ROLES_TR15_ARBAC );
    }


    /**
     *
     * @param msg
     * @param op
     * @param uraArray
     * @param uaArray
     * @param uArray
     * @param rArray
     */
    public static void canAssignUsers( String msg, ASSIGN_OP op, String[][] uraArray, String[][] uaArray,
        String[][] uArray,
        String[][] rArray )
    {
        LogUtil.logIt( msg );
        Role role;
        Map<URA, URA> uraTestResults = URATestData.getURAs( uraArray );

        try
        {
            DelAccessMgr delAccessMgr = DelAccessMgrFactory.createInstance( TestUtils.getContext() );
            AccessMgr accessMgr = ( AccessMgr ) delAccessMgr;
            int i = 0;
            for ( String[] aUsr : uaArray )
            {
                User aUser = UserTestData.getUser( aUsr );
                Session session = accessMgr.createSession( aUser, false );
                assertNotNull( session );
                delAccessMgr.setAdmin( session );
                for ( String[] usr : uArray )
                {
                    User user = UserTestData.getUser( usr );
                    i++;
                    for ( String[] rle : rArray )
                    {
                        role = RoleTestData.getRole( rle );
                        String methodName;
                        boolean result;
                        if ( op == ASSIGN_OP.ASSIGN )
                        {
                            result = delAccessMgr.canAssign( session, user, role );
                            methodName = ".canAssignUsers";
                        }
                        else
                        {
                            result = delAccessMgr.canDeassign( session, user, role );
                            methodName = ".canDeassignUsers";
                        }

                        List<UserAdminRole> aRoles = session.getAdminRoles();
                        assertNotNull( aRoles );
                        assertTrue( CLS_NM + methodName + " Admin User invalid number of roles", aRoles.size() == 1 );
                        // since this user should only have one admin role, get the first one from list:
                        UserAdminRole aRole = aRoles.get( 0 );
                        URA sourceUra = new URA( aRole.getName(), user.getOu(), role.getName(), result );
                        URA targetUra = uraTestResults.get( sourceUra );
                        assertTrue( CLS_NM + methodName + " cannot find target URA admin role [" + sourceUra.getArole()
                            + " uou [" + sourceUra.getUou() + "] role [" + sourceUra.getUrole() + "] Result ["
                            + sourceUra.isCanAssign() + "] actual result [" + result + "]", targetUra != null );
                        LOG.debug( methodName + " User [" + user.getUserId()
                            + "] success URA using admin role [" + targetUra.getArole() + " uou [" + targetUra.getUou()
                            + "] role [" + targetUra.getUrole() + "] target result [" + targetUra.isCanAssign()
                            + "] actual result [" + result + "]" );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( "canAssignUsers op [" + op + "] caught SecurityException rc=" + ex.getErrorId()
                + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testCanGrantPerm()
    {
        canGrantPerms( "CAN-GRNT-PRMS PRA_T1 TU17A TOB5 TR15", GRANT_OP.GRANT, PRATestData.PRA_T1,
            UserTestData.USERS_TU17A_ARBAC, PermTestData.OBJS_TOB5, RoleTestData.ROLES_TR15_ARBAC );
    }


    public void testCanRevokePerm()
    {
        canGrantPerms( "CAN-RVKE-PRMS PRA_T1 TU17A TOB5 TR15", GRANT_OP.REVOKE, PRATestData.PRA_T1,
            UserTestData.USERS_TU17A_ARBAC, PermTestData.OBJS_TOB5, RoleTestData.ROLES_TR15_ARBAC );
    }

    public enum GRANT_OP
    {
        GRANT, REVOKE
    }


    /**
     *
     * @param msg
     * @param op
     * @param uraArray
     * @param uaArray
     * @param pArray
     * @param rArray
     */
    public static void canGrantPerms( String msg, GRANT_OP op, String[][] uraArray, String[][] uaArray,
        String[][] pArray,
        String[][] rArray )
    {
        LogUtil.logIt( msg );
        Role role;
        Map<PRA, PRA> praTestResults = PRATestData.getPRAs( uraArray );

        try
        {
            DelAccessMgr delAccessMgr = DelAccessMgrFactory.createInstance( TestUtils.getContext() );
            AccessMgr accessMgr = ( AccessMgr ) delAccessMgr;
            int i = 0;
            for ( String[] aUsr : uaArray )
            {
                User aUser = UserTestData.getUser( aUsr );
                Session session = accessMgr.createSession( aUser, false );
                assertNotNull( session );
                for ( String[] prm : pArray )
                {
                    PermObj pObj = PermTestData.getObj( prm );
                    i++;
                    for ( String[] rle : rArray )
                    {
                        role = RoleTestData.getRole( rle );
                        String methodName;
                        boolean result;
                        if ( op == GRANT_OP.GRANT )
                        {
                            result = delAccessMgr.canGrant( session, role, new Permission( pObj.getObjName(), "" ) );
                            methodName = ".canGrantPerms";
                        }
                        else
                        {
                            result = delAccessMgr.canRevoke( session, role, new Permission( pObj.getObjName(), "" ) );
                            methodName = ".canRevokePerms";
                        }

                        List<UserAdminRole> aRoles = session.getAdminRoles();
                        assertNotNull( aRoles );
                        assertTrue( CLS_NM + methodName + " Admin User invalid number of roles", aRoles.size() == 1 );
                        UserAdminRole aRole = aRoles.get( 0 );
                        PRA sourceUra = new PRA( aRole.getName(), pObj.getOu(), role.getName(), result );
                        PRA targetUra = praTestResults.get( sourceUra );
                        assertTrue( CLS_NM + methodName + " cannot find target PRA admin role [" + sourceUra.getArole()
                            + " pou [" + sourceUra.getPou() + "] role [" + sourceUra.getUrole() + "] Result ["
                            + sourceUra.isCanAssign() + "] actual result [" + result + "]", targetUra != null );
                        LOG.debug( methodName + " failed target PRA admin role [" + targetUra.getArole()
                            + " pou [" + targetUra.getPou() + "] role [" + targetUra.getUrole() + "] target result ["
                            + targetUra.isCanAssign() + "] actual result [" + result + "]" );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( "canGrantPerms op [" + op + "] caught SecurityException rc=" + ex.getErrorId()
                + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddOrgUnit()
    {
        //addOrgUnits("ADD ORGS_USR_DEV0", OrgUnitTestData.ORGS_USR_DEV0);
        addOrgUnits( "ADD ORGS_TO1", OrgUnitTestData.ORGS_TO1 );
        addOrgUnits( "ADD ORGS_USR_TO2", OrgUnitTestData.ORGS_USR_TO2 );
        addOrgUnits( "ADD ORGS_ORGS_PRM_TO3", OrgUnitTestData.ORGS_PRM_TO3 );
        addOrgUnits( "ADD ORGS_PRM_TO4", OrgUnitTestData.ORGS_PRM_TO4 );
        addOrgUnits( "ADD ORGS_USR_TO5", OrgUnitTestData.ORGS_USR_TO5 );
        addOrgUnits( "ADD ORGS_PRM_TO5", OrgUnitTestData.ORGS_PRM_TO5 );
        // The DEV1 OU is not removed during cleanup phase because the test system users belong to it:
        if ( FortressJUnitTest.isFirstRun() )
        {
            addOrgUnits( "ADD ORGS_DEV1", OrgUnitTestData.ORGS_DEV1 );
        }
        addOrgUnits( "ADD ORGS_APP1", OrgUnitTestData.ORGS_APP1 );
    }


    public static void addOrgUnit( String msg, String[] org )
    {
        LogUtil.logIt( msg );
        
        try
        {
            DelAdminMgr dAdminMgr = DelAdminMgrFactory.createInstance( TestUtils.getContext() );
            OrgUnit ou = OrgUnitTestData.getOrgUnit( org );
            OrgUnit entity = dAdminMgr.add( ou );
            LOG.debug( "addOrgUnit ou [{}] successful", entity.getName() );
        }
        catch ( SecurityException ex )
        {
            LOG.error( "addOrgUnit caught SecurityException rc={}, msg={}", ex.getErrorId(), ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     *
     * @param msg
     * @param oArray
     */
    public static void addOrgUnits( String msg, String[][] oArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit ou = OrgUnitTestData.getOrgUnit( ole );
                OrgUnit entity = dAdminMgr.add( ou );
                LOG.debug( "addOrgUnits ou [" + entity.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( "addOrgUnits caught SecurityException=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testDeleteOrgUnit()
    {
        //deleteOrgUnits("DEL ORGS_USR_DEV0", OrgUnitTestData.ORGS_USR_DEV0);
        deleteOrgUnits( "DEL ORGS_TO1", OrgUnitTestData.ORGS_TO1 );
        deleteOrgUnits( "DEL ORGS_USR_TO2", OrgUnitTestData.ORGS_USR_TO2 );
        deleteOrgUnits( "DEL ORGS_PRM_TO3", OrgUnitTestData.ORGS_PRM_TO3 );
        deleteOrgUnits( "DEL ORGS_PRM_TO4", OrgUnitTestData.ORGS_PRM_TO4 );
        deleteOrgUnits( "DEL ORGS_USR_TO5", OrgUnitTestData.ORGS_USR_TO5 );
        deleteOrgUnits( "DEL ORGS_PRM_TO5", OrgUnitTestData.ORGS_PRM_TO5 );
        // Don't delete because the test system users will belong to DEV1 OU and cannot be removed by normal API call:
        // deleteOrgUnits("DEL ORGS_DEV1", OrgUnitTestData.ORGS_DEV1);
        deleteOrgUnits( "DEL ORGS_APP1", OrgUnitTestData.ORGS_APP1 );
    }


    /**
     *
     * @param msg
     * @param org
     */
    private void deleteOrgUnit( String msg, String[] org )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            OrgUnit ou = OrgUnitTestData.getOrgUnit( org );
            dAdminMgr.delete( ou );
            LOG.debug( "deleteOrgUnit ou [" + ou.getName() + "] successful" );
        }
        catch ( SecurityException ex )
        {
            LOG.error( "deleteOrgUnit caught SecurityException=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     *
     * @param msg
     * @param oArray
     */
    private void deleteOrgUnits( String msg, String[][] oArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit ou = OrgUnitTestData.getOrgUnit( ole );
                dAdminMgr.delete( ou );
                LOG.debug( "deleteOrgUnits ou [" + ou.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "deleteOrgUnits caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(),
                ex );
            fail( ex.getMessage() );
        }
    }


    public void testUpdateOrgUnit()
    {
        updateOrgUnits( "UPD ORGS_TO1", OrgUnitTestData.ORGS_TO1 );
        updateOrgUnits( "UPD ORGS_PRM_TO3", OrgUnitTestData.ORGS_PRM_TO3 );

    }


    /**
     *
     * @param msg
     * @param oArray
     */
    public static void updateOrgUnits( String msg, String[][] oArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit ou = OrgUnitTestData.getOrgUnit( ole );
                dAdminMgr.update( ou );
                LOG.debug( "updateOrgUnits ou [" + ou.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "updateOrgUnits caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(),
                ex );
            fail( ex.getMessage() );
        }
    }


    public void testReadOrgUnit()
    {
        // public Role readRole(Role role)
        readOrgUnits( "RD ORGS_TO1", OrgUnitTestData.ORGS_TO1 );
        readOrgUnits( "RD ORGS_PRM_TO3", OrgUnitTestData.ORGS_PRM_TO3 );
    }


    /**
     *
     * @param msg
     * @param oArray
     */
    public static void readOrgUnits( String msg, String[][] oArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelReviewMgr dReviewMgr = getManagedDelegatedReviewMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit ou = OrgUnitTestData.getOrgUnit( ole );
                OrgUnit entity = dReviewMgr.read( ou );
                OrgUnitTestData.assertEquals( entity, ole );
                LOG.debug( "readOrgUnits [" + entity.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "readOrgUnits caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(),
                ex );
            fail( ex.getMessage() );
        }
    }


    public void testSearchOrgUnits()
    {
        searchOrgUnits( "SRCH ORGS_TO1",
            TestUtils.getSrchValue( OrgUnitTestData.getName( OrgUnitTestData.ORGS_TO1[0] ) ), OrgUnitTestData.ORGS_TO1 );
        searchOrgUnits( "SRCH ORGS_PRM_TO3",
            TestUtils.getSrchValue( OrgUnitTestData.getName( OrgUnitTestData.ORGS_PRM_TO3[0] ) ),
            OrgUnitTestData.ORGS_PRM_TO3 );
    }


    /**
     *
     * @param msg
     * @param srchValue
     * @param oArray
     */
    public static void searchOrgUnits( String msg, String srchValue, String[][] oArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelReviewMgr dReviewMgr = getManagedDelegatedReviewMgr();
            // grab the type from the first entry in the test org list:
            OrgUnit.Type type = OrgUnitTestData.getType( oArray[0] );
            List<OrgUnit> ous = dReviewMgr.search( type, srchValue );
            assertNotNull( ous );
            assertTrue( "searchOrgUnits list size check", oArray.length == ous.size() );
            for ( String[] ole : oArray )
            {
                int indx = ous.indexOf( new OrgUnit( OrgUnitTestData.getName( ole ) ) );
                if ( indx != -1 )
                {
                    OrgUnit entity = ous.get( indx );
                    assertNotNull( entity );
                    OrgUnitTestData.assertEquals( entity, ole );
                    LOG.debug( "searchOrgUnits [" + entity.getName() + "] successful" );
                }
                else
                {
                    msg = "searchOrgUnits srchValue [" + srchValue + "] failed list search";
                    LogUtil.logIt( msg );
                    fail( msg );
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "searchOrgUnits srchValue [" + srchValue + "] caught SecurityException rc=" + ex.getErrorId()
                    + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddOrgInheritance()
    {
        addInheritedOrgUnits( "ADD-INHERIT ORGS_USR_TO2", OrgUnitTestData.ORGS_USR_TO2 );
        addInheritedOrgUnits( "ADD-INHERIT ORGS_PRM_TO4", OrgUnitTestData.ORGS_PRM_TO4 );
        addInheritedOrgUnits( "ADD-INHERIT ORGS_USR_TO5", OrgUnitTestData.ORGS_USR_TO5 );
        addInheritedOrgUnits( "ADD-INHERIT ORGS_PRM_TO5", OrgUnitTestData.ORGS_PRM_TO5 );
    }


    /**
     *
     * @param msg
     * @param oArray
     */
    public static void addInheritedOrgUnits( String msg, String[][] oArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit child = OrgUnitTestData.getOrgUnit( ole );
                Set<String> parents = new HashSet<String>();
                OrgUnitTestData.getRelationship( parents, ole );

                for ( String pOrg : parents )
                {
                    OrgUnit parent = new OrgUnit( pOrg );
                    parent.setType( child.getType() );
                    dAdminMgr.addInheritance( parent, child );
                    LOG.debug( "addInheritedOrgUnits child org [" + child.getName() + "] parent org ["
                        + pOrg + "] successful" );
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "addInheritedOrgUnits caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testDeleteOrgInheritance()
    {
        deleteInheritedOrgUnits( "DEL-INHERIT ORGS_USR_TO2", OrgUnitTestData.ORGS_USR_TO2 );
        deleteInheritedOrgUnits( "DEL-INHERIT ORGS_PRM_TO4", OrgUnitTestData.ORGS_PRM_TO4 );
        deleteInheritedOrgUnits( "DEL-INHERIT ORGS_USR_TO5", OrgUnitTestData.ORGS_USR_TO5 );
        deleteInheritedOrgUnits( "DEL-INHERIT ORGS_PRM_TO5", OrgUnitTestData.ORGS_PRM_TO5 );
    }


    /**
     * 
     * @param msg
     * @param oArray
     */
    private void deleteInheritedOrgUnits( String msg, String[][] oArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit child = OrgUnitTestData.getOrgUnit( ole );
                Set<String> parents = new HashSet<String>();
                OrgUnitTestData.getRelationship( parents, ole );

                for ( String pOrg : parents )
                {
                    OrgUnit parent = new OrgUnit( pOrg );
                    parent.setType( child.getType() );
                    //public void deleteInheritance(OrgUnit parent, OrgUnit child)
                    dAdminMgr.deleteInheritance( parent, child );
                    LOG.debug( "deleteInheritedOrgUnits child org [" + child.getName() + "] parent org ["
                        + pOrg + "] successful" );
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( "deleteInheritedOrgUnits caught SecurityException rc=" + ex.getErrorId() + ", msg="
                + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testReadAdminRole()
    {
        // public Role readRole(Role role)
        readAdminRoles( "RD-ADMRLS TR1", AdminRoleTestData.AROLES_TR1 );
        readAdminRoles( "RD-ADMRLS TR2", AdminRoleTestData.AROLES_TR2 );
        readAdminRoles( "RD-ADMRLS TR3_UPD", AdminRoleTestData.AROLES_TR3_UPD );
    }


    /**
     *
     * @param msg
     * @param rArray
     */
    public static void readAdminRoles( String msg, String[][] rArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelReviewMgr dReviewMgr = getManagedDelegatedReviewMgr();
            for ( String[] rle : rArray )
            {
                AdminRole entity = dReviewMgr.readRole( AdminRoleTestData.getRole( rle ) );
                AdminRoleTestData.assertEquals( entity, rle );
                LOG.debug( "readAdminRoles [" + entity.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( "readAdminRoles caught SecurityException=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testSearchAdminRole()
    {
        searchAdminRoles( "SRCH-ADMRLS TR1",
            TestUtils.getSrchValue( RoleTestData.getName( AdminRoleTestData.AROLES_TR1[0] ) ),
            AdminRoleTestData.AROLES_TR1 );
        searchAdminRoles( "SRCH-ADMRLS TR2",
            TestUtils.getSrchValue( RoleTestData.getName( AdminRoleTestData.AROLES_TR2[0] ) ),
            AdminRoleTestData.AROLES_TR2 );
        searchAdminRoles( "SRCH-ADMRLS TR3",
            TestUtils.getSrchValue( RoleTestData.getName( AdminRoleTestData.AROLES_TR3_UPD[0] ) ),
            AdminRoleTestData.AROLES_TR3_UPD );
    }


    /**
     *
     * @param msg
     * @param srchValue
     * @param rArray
     */
    public static void searchAdminRoles( String msg, String srchValue, String[][] rArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelReviewMgr dReviewMgr = getManagedDelegatedReviewMgr();
            List<AdminRole> roles = dReviewMgr.findRoles( srchValue );
            assertNotNull( roles );
            assertTrue( CLS_NM + "searchAdminRoles list size check", rArray.length == roles.size() );
            for ( String[] rle : rArray )
            {
                int indx = roles.indexOf( AdminRoleTestData.getRole( rle ) );
                if ( indx != -1 )
                {
                    AdminRole entity = roles.get( indx );
                    assertNotNull( entity );
                    AdminRoleTestData.assertEquals( entity, rle );
                    LOG.debug( "searchAdminRoles [" + entity.getName() + "] successful" );
                }
                else
                {
                    msg = "searchAdminRoles srchValue [" + srchValue + "] failed list search";
                    LogUtil.logIt( msg );
                    fail( msg );
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "searchAdminRoles srchValue [" + srchValue + "] caught SecurityException rc="
                    + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddOrgUnitDescendant()
    {
        addOrgUnitDescendant( "ADD ORGS-USR-TO6-DESC", OrgUnitTestData.ORGS_USR_TO6_DSC, OrgUnit.Type.USER );
        addOrgUnitDescendant( "ADD ORGS-PRM-TO6-DESC", OrgUnitTestData.ORGS_PRM_TO6_DSC, OrgUnit.Type.PERM );
    }


    /**
     *
     * @param msg
     * @param oArray
     */
    public static void addOrgUnitDescendant( String msg, String[][] oArray, OrgUnit.Type type )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            int ctr = 0;
            for ( String[] ole : oArray )
            {
                OrgUnit orgUnit = OrgUnitTestData.getOrgUnit( ole );
                if ( ctr++ == 0 || OrgUnitTestData.isTree( ole ) )
                {
                    dAdminMgr.add( orgUnit );
                    LOG.debug( "addOrgUnitDescendant add orgUnit [" + orgUnit.getName() + "] successful" );
                }

                // use list because order is important for test structure:
                List<String> descs = new ArrayList<String>();
                OrgUnitTestData.getRelationship( descs, ole );

                if ( OrgUnitTestData.isTree( ole ) )
                {
                    OrgUnit parent = orgUnit;
                    for ( String desc : descs )
                    {
                        OrgUnit child = new OrgUnit( desc, type );
                        dAdminMgr.addDescendant( parent, new OrgUnit( desc, type ) );
                        LOG.debug( "addOrgUnitDescendant asc orgUnit [" + orgUnit.getName()
                            + "] desc orgUnit [" + desc + "] successful" );
                        parent = child;
                    }
                }
                else
                {
                    for ( String desc : descs )
                    {
                        dAdminMgr.addDescendant( orgUnit, new OrgUnit( desc, type ) );
                        LOG.debug( "addOrgUnitDescendant asc orgUnit [" + orgUnit.getName()
                            + "] desc orgUnit [" + desc + "] successful" );
                    }
                }

                Set<String> inheritances = OrgUnitTestData.getInheritances( ole );
                if ( inheritances != null )
                {
                    for ( String desc : inheritances )
                    {
                        dAdminMgr.addInheritance( orgUnit, new OrgUnit( desc, type ) );
                        LOG.debug( "addOrgUnitDescendant asc orgUnit [" + orgUnit.getName()
                            + "] desc orgUnit [" + desc + "] successful" );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "addOrgUnitDescendant caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testDelOrgUnitDescendant() throws SecurityException
    {
        delOrgUnitDescendant( "DEL-ORGS-USR-TO6-DESC", OrgUnitTestData.ORGS_USR_TO6_DSC, OrgUnit.Type.USER );
        delOrgUnitDescendant( "DEL-ORGS-PRM-TO6-DESC", OrgUnitTestData.ORGS_PRM_TO6_DSC, OrgUnit.Type.PERM );
    }


    /**
     *
     * @param msg
     */
    private void delOrgUnitDescendant( String msg, String[][] oArray, OrgUnit.Type type )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit orgUnit = OrgUnitTestData.getOrgUnit( ole );
                // use list because order is important for test structure:
                List<String> descs = new ArrayList<String>();
                OrgUnitTestData.getRelationship( descs, ole );

                if ( OrgUnitTestData.isTree( ole ) )
                {
                    OrgUnit parent = orgUnit;
                    for ( String desc : descs )
                    {
                        OrgUnit child = new OrgUnit( desc );
                        dAdminMgr.deleteInheritance( parent, new OrgUnit( desc, type ) );
                        LOG.debug( "delOrgUnitDescendant asc orgUnit [" + orgUnit.getName()
                            + "] desc orgUnit [" + desc + "] successful" );
                        parent = child;
                    }
                }
                else
                {
                    for ( String desc : descs )
                    {
                        dAdminMgr.deleteInheritance( orgUnit, new OrgUnit( desc, type ) );
                        LOG.debug( "delOrgUnitDescendant asc orgUnit [" + orgUnit.getName()
                            + "] desc orgUnit [" + desc + "] successful" );
                    }
                }

                Set<String> inheritances = OrgUnitTestData.getInheritances( ole );
                if ( inheritances != null )
                {
                    for ( String desc : inheritances )
                    {
                        dAdminMgr.deleteInheritance( orgUnit, new OrgUnit( desc, type ) );
                        LOG.debug( "delOrgUnitDescendant asc orgUnit [" + orgUnit.getName()
                            + "] desc orgUnit [" + desc + "] successful" );
                    }
                }
                dAdminMgr.delete( orgUnit );
                LOG.debug( "delOrgUnitDescendant remove asc orgUnit [" + orgUnit.getName() + "] successful" );
            }

            // cleanup the last row of descendants from orgUnit data set.
            DelReviewMgr dReviewMgr = getManagedDelegatedReviewMgr();
            String orgUnitSrchVal = TestUtils.getSrchValue( OrgUnitTestData.getName( oArray[0] ) );
            List<OrgUnit> cleanup = dReviewMgr.search( type, orgUnitSrchVal );
            for ( OrgUnit oe : cleanup )
            {
                dAdminMgr.delete( oe );
                LOG.debug( "delOrgUnitDescendant cleanup orgUnit [" + oe.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "delOrgUnitDescendant caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddOrgUnitAscendants()
    {
        addOrgUnitAscendant( "ADD-ORGS-USR-TR7-ASC", OrgUnitTestData.ORGS_USR_TO7_ASC, OrgUnit.Type.USER );
        addOrgUnitAscendant( "ADD-ORGS-PRM-TR7-ASC", OrgUnitTestData.ORGS_PRM_TO7_ASC, OrgUnit.Type.PERM );

    }


    /**
     *
     * @param msg
     * @param oArray
     * @param type
     */
    public static void addOrgUnitAscendant( String msg, String[][] oArray, OrgUnit.Type type )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit orgUnit = OrgUnitTestData.getOrgUnit( ole );
                if ( OrgUnitTestData.isCreate( ole ) )
                {
                    dAdminMgr.add( orgUnit );
                    LOG.debug( "addOrgUnitAscendant add orgUnit [" + orgUnit.getName() + "] successful" );
                }

                Set<String> ascs = new HashSet<String>();
                OrgUnitTestData.getRelationship( ascs, ole );

                for ( String asc : ascs )
                {
                    dAdminMgr.addAscendant( orgUnit, new OrgUnit( asc, type ) );
                    LOG.debug( "addOrgUnitAscendant desc role [" + orgUnit.getName() + "] asc role ["
                        + asc + "] successful" );
                }

                Set<String> inheritances = OrgUnitTestData.getInheritances( ole );
                if ( inheritances != null )
                {
                    for ( String asc : inheritances )
                    {
                        dAdminMgr.addInheritance( new OrgUnit( asc, type ), orgUnit );
                        LOG.debug( "addOrgUnitAscendant desc role [" + orgUnit.getName() + "] asc role ["
                            + asc + "] successful" );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "addOrgUnitAscendant caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testDelOrgUnitAscendant()
    {
        delOrgUnitAscendant( "DEL-ORGS-USR-TR7-ASC", OrgUnitTestData.ORGS_USR_TO7_ASC, OrgUnit.Type.USER );
        delOrgUnitAscendant( "DEL-ORGS-PRM-TR7-ASC", OrgUnitTestData.ORGS_PRM_TO7_ASC, OrgUnit.Type.PERM );
    }


    /**
     *
     * @param msg
     * @param oArray
     */
    private void delOrgUnitAscendant( String msg, String[][] oArray, OrgUnit.Type type )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] ole : oArray )
            {
                OrgUnit orgUnit = OrgUnitTestData.getOrgUnit( ole );
                Set<String> ascs = new HashSet<String>();
                OrgUnitTestData.getRelationship( ascs, ole );

                for ( String asc : ascs )
                {
                    dAdminMgr.deleteInheritance( new OrgUnit( asc, type ), orgUnit );
                    LOG.debug( "delOrgUnitAscendant desc orgUnit [" + orgUnit.getName()
                        + "] asc orgUnit [" + asc + "] successful" );
                }

                Set<String> inheritances = OrgUnitTestData.getInheritances( ole );
                if ( inheritances != null )
                {
                    for ( String asc : inheritances )
                    {
                        dAdminMgr.deleteInheritance( new OrgUnit( asc, type ), orgUnit );
                        LOG.debug( "delOrgUnitAscendant desc orgUnit [" + orgUnit.getName()
                            + "] asc orgUnit [" + asc + "] successful" );
                    }
                }
                dAdminMgr.delete( orgUnit );
                LOG.debug( "delOrgUnitAscendant remove desc orgUnit [" + orgUnit.getName() + "] successful" );
            }

            // cleanup the top ascendant from orgUnit data set.
            DelReviewMgr dReviewMgr = getManagedDelegatedReviewMgr();
            String orgUnitSrchVal = OrgUnitTestData.getName( oArray[0] );
            // stip off prefix and search:
            orgUnitSrchVal = orgUnitSrchVal.substring( 0, 3 );
            List<OrgUnit> cleanup = dReviewMgr.search( type, orgUnitSrchVal );
            for ( OrgUnit oe : cleanup )
            {
                dAdminMgr.delete( oe );
                LOG.debug( "delOrgUnitAscendant cleanup orgUnit [" + oe.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "delOrgUnitAscendant caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddAdminRoleDescendant()
    {
        addAdminRoleDescendant( "ADD-ARLS-TR5-DESC", AdminRoleTestData.AROLES_TR5_DSC );
    }


    /**
     *
     * @param msg
     * @param rArray
     */
    public static void addAdminRoleDescendant( String msg, String[][] rArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            int ctr = 0;
            for ( String[] rle : rArray )
            {
                AdminRole adminRole = AdminRoleTestData.getRole( rle );
                if ( ctr++ == 0 || RoleTestData.isTree( rle ) )
                {
                    dAdminMgr.addRole( adminRole );
                    LOG.debug( "addAdminRoleDescendant add role [" + adminRole.getName() + "] successful" );
                }

                // use list because order is important for test structure:
                List<String> descs = RoleTestData.getRelationshipList( rle );
                if ( descs != null )
                {
                    if ( RoleTestData.isTree( rle ) )
                    {
                        AdminRole parent = adminRole;
                        for ( String desc : descs )
                        {
                            AdminRole child = new AdminRole( desc );
                            dAdminMgr.addDescendant( parent, new AdminRole( desc ) );
                            LOG.debug( "addAdminRoleDescendant asc role [" + adminRole.getName()
                                + "] desc role [" + desc + "] successful" );
                            parent = child;
                        }
                    }
                    else
                    {
                        for ( String desc : descs )
                        {
                            dAdminMgr.addDescendant( adminRole, new AdminRole( desc ) );
                            LOG.debug( "addAdminRoleDescendant asc role [" + adminRole.getName()
                                + "] desc role [" + desc + "] successful" );
                        }
                    }
                }

                Set<String> inheritances = RoleTestData.getInheritances( rle );
                if ( inheritances != null )
                {
                    for ( String desc : inheritances )
                    {
                        dAdminMgr.addInheritance( adminRole, new AdminRole( desc ) );
                        LOG.debug( "addAdminRoleDescendant asc role [" + adminRole.getName()
                            + "] desc role [" + desc + "] successful" );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( "addAdminRoleDescendant caught SecurityException rc=" + ex.getErrorId() + ", msg="
                + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testDelAdminRoleDescendant() throws SecurityException
    {
        delAdminRoleDescendant( "DEL-ARLS-TR5-DESC", AdminRoleTestData.AROLES_TR5_DSC );
    }


    private void delAdminRoleDescendant( String msg, String[][] rArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] rle : rArray )
            {
                AdminRole adminRole = AdminRoleTestData.getRole( rle );
                // use list because order is important for test structure:
                List<String> descs = RoleTestData.getRelationshipList( rle );
                if ( descs != null )
                {
                    if ( RoleTestData.isTree( rle ) )
                    {
                        AdminRole parent = adminRole;
                        for ( String desc : descs )
                        {
                            AdminRole child = new AdminRole( desc );
                            dAdminMgr.deleteInheritance( parent, new AdminRole( desc ) );
                            LOG.debug( "delAdminRoleDescendant asc adminRole [" + adminRole.getName()
                                + "] desc adminRole [" + desc + "] successful" );
                            parent = child;
                        }
                    }
                    else
                    {
                        for ( String desc : descs )
                        {
                            dAdminMgr.deleteInheritance( adminRole, new AdminRole( desc ) );
                            LOG.debug( "delAdminRoleDescendant asc adminRole [" + adminRole.getName()
                                + "] desc adminRole [" + desc + "] successful" );
                        }
                    }
                }

                Set<String> inheritances = RoleTestData.getInheritances( rle );
                if ( inheritances != null )
                {
                    for ( String desc : inheritances )
                    {
                        dAdminMgr.deleteInheritance( adminRole, new AdminRole( desc ) );
                        LOG.debug( "delAdminRoleDescendant asc adminRole [" + adminRole.getName()
                            + "] desc adminRole [" + desc + "] successful" );
                    }
                }
                dAdminMgr.deleteRole( adminRole );
                LOG.debug( "delAdminRoleDescendant remove asc adminRole [" + adminRole.getName()
                    + "] successful" );
            }

            // cleanup the last row of descendants from orgUnit data set.
            DelReviewMgr dReviewMgr = getManagedDelegatedReviewMgr();
            String srchVal = TestUtils.getSrchValue( RoleTestData.getName( rArray[0] ) );
            List<AdminRole> cleanup = dReviewMgr.findRoles( srchVal );
            
            for ( Role re : cleanup )
            {
                dAdminMgr.deleteRole( (AdminRole)re );
                LOG.debug( "delAdminRoleDescendant cleanup adminRole [" + re.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "delOrgUnitDescendant caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddAdminRoleAscendants()
    {
        addAdminRoleAscendant( "ADD-ARLS-TR4-ASC", AdminRoleTestData.AROLES_TR4_ASC );
    }


    /**
     *
     * @param msg
     * @param rArray
     */
    public static void addAdminRoleAscendant( String msg, String[][] rArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] rle : rArray )
            {
                AdminRole adminRole = AdminRoleTestData.getRole( rle );
                if ( RoleTestData.isCreate( rle ) )
                {
                    dAdminMgr.addRole( adminRole );
                    LOG.debug( "addAdminRoleAscendant add adminRole [" + adminRole.getName() + "] successful" );
                }
                Set<String> ascs = RoleTestData.getRelationships( rle );
                if ( ascs != null )
                {
                    for ( String asc : ascs )
                    {
                        dAdminMgr.addAscendant( adminRole, new AdminRole( asc ) );
                        LOG.debug( "addAdminRoleAscendant desc role [" + adminRole.getName() + "] asc role ["
                            + asc + "] successful" );
                    }
                }
                Set<String> inheritances = RoleTestData.getInheritances( rle );
                if ( inheritances != null )
                {
                    for ( String asc : inheritances )
                    {
                        dAdminMgr.addInheritance( new AdminRole( asc ), adminRole );
                        LOG.debug( "addAdminRoleAscendant desc role [" + adminRole.getName() + "] asc role ["
                            + asc + "] successful" );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "addAdminRoleAscendant caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testDelAdminRoleAscendant()
    {
        delAdminRoleAscendant( "DEL-ARLS-TR4-ASC", AdminRoleTestData.AROLES_TR4_ASC );
    }


    /**
     *
     * @param msg
     * @param rArray
     */
    private void delAdminRoleAscendant( String msg, String[][] rArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] rle : rArray )
            {
                AdminRole adminRole = AdminRoleTestData.getRole( rle );
                Set<String> ascs = RoleTestData.getRelationships( rle );
                if ( ascs != null )
                {
                    for ( String asc : ascs )
                    {
                        dAdminMgr.deleteInheritance( new AdminRole( asc ), adminRole );
                        LOG.debug( "delAdminRoleAscendant desc adminRole [" + adminRole.getName()
                            + "] asc adminRole [" + asc + "] successful" );
                    }
                }

                Set<String> inheritances = RoleTestData.getInheritances( rle );
                if ( inheritances != null )
                {
                    for ( String asc : inheritances )
                    {
                        dAdminMgr.deleteInheritance( new AdminRole( asc ), adminRole );
                        LOG.debug( "delAdminRoleAscendant desc adminRole [" + adminRole.getName()
                            + "] asc orgUnit [" + asc + "] successful" );
                    }
                }
                dAdminMgr.deleteRole( adminRole );
                LOG.debug( "delAdminRoleAscendant remove desc adminRole [" + adminRole.getName()
                    + "] successful" );
            }

            // cleanup the top ascendant from orgUnit data set.
            DelReviewMgr dReviewMgr = getManagedDelegatedReviewMgr();
            String adminRoleSrchVal = RoleTestData.getName( rArray[0] );
            // stip off prefix and search:
            adminRoleSrchVal = adminRoleSrchVal.substring( 0, 3 );
            List<AdminRole> cleanup = dReviewMgr.findRoles( adminRoleSrchVal );
            for ( AdminRole re : cleanup )
            {
                dAdminMgr.deleteRole( re );
                LOG.debug( "delAdminRoleAscendant cleanup adminRole [" + re.getName() + "] successful" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                "delAdminRoleAscendant caught SecurityException rc=" + ex.getErrorId() + ", msg="
                    + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testAddAdminRoleInheritance()
    {
        addInheritedAdminRoles( "ADD-ARLS-TR6-HIER", AdminRoleTestData.AROLES_TR6_HIER );
    }


    /**
     *
     * @param msg
     * @param rArray
     */
    public static void addInheritedAdminRoles( String msg, String[][] rArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] rle : rArray )
            {
                AdminRole role = AdminRoleTestData.getRole( rle );
                Set<String> parents = RoleTestData.getRelationships( rle );
                if ( parents != null )
                {
                    for ( String pRole : parents )
                    {
                        dAdminMgr.addInheritance( new AdminRole( pRole ), role );
                        LOG.debug( "addInheritedAdminRoles child role [" + role.getName() + "] parent role ["
                            + pRole + "] successful" );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( "addInheritedAdminRoles caught SecurityException rc=" + ex.getErrorId() + ", msg="
                + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    public void testDeleteAdminRoleInheritance()
    {
        deleteInheritedAdminRoles( "DEL-ARLS-TR6-HIER", AdminRoleTestData.AROLES_TR6_HIER );
    }


    /**
     *
     * @param msg
     * @param rArray
     */
    private static void deleteInheritedAdminRoles( String msg, String[][] rArray )
    {
        LogUtil.logIt( msg );
        try
        {
            DelAdminMgr dAdminMgr = getManagedDelegatedMgr();
            for ( String[] rle : rArray )
            {
                AdminRole role = AdminRoleTestData.getRole( rle );
                Set<String> parents = RoleTestData.getRelationships( rle );
                if ( parents != null )
                {
                    for ( String pRole : parents )
                    {
                        dAdminMgr.deleteInheritance( new AdminRole( pRole ), role );
                        LOG.debug( "deleteInheritedAdminRoles child role [" + role.getName()
                            + "] parent role [" + pRole + "] successful" );
                    }
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( "deleteInheritedAdminRoles caught SecurityException rc=" + ex.getErrorId() + ", msg="
                + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     *
     * @return
     * @throws SecurityException
     */
    private static DelReviewMgr getManagedDelegatedReviewMgr() throws SecurityException
    {
        DelReviewMgr dReviewMgr = DelReviewMgrFactory.createInstance( TestUtils.getContext() );
        if ( FortressJUnitTest.isAdminEnabled() && adminSess == null )
        {
            adminSess = DelegatedMgrImplTest.createAdminSession();
        }
        dReviewMgr.setAdmin( adminSess );
        return dReviewMgr;
    }


    private static DelReviewMgr getDelegatedReviewMgr() throws SecurityException
    {
        return DelReviewMgrFactory.createInstance( TestUtils.getContext() );
    }


    /**
     *
     * @return
     * @throws SecurityException
     */
    private static DelAdminMgr getManagedDelegatedMgr() throws SecurityException
    {
        if ( FortressJUnitTest.isAdminEnabled() && adminSess == null )
        {
            adminSess = DelegatedMgrImplTest.createAdminSession();
        }
        return DelAdminMgrFactory.createInstance( TestUtils.getContext(), adminSess );
    }


    /**
     *
     * @return
     */
    public static boolean loadAdminPolicy()
    {
        boolean result = true;
        try
        {
            ReviewMgr rMgr = ReviewMgrFactory.createInstance( TestUtils.getContext() );
            User admin = UserTestData.getUser( UserTestData.USERS_TU0[0] );
            rMgr.readUser( admin );
            result = false;
        }
        catch ( SecurityException se )
        {
            String info = " loadAdminPolicy detected admin policy not loaded";
            LOG.debug( info );
        }
        return result;
    }


    /**
     *
     */
    public static Session createAdminSession()
    {
        Session adminSess = null;
        try
        {
            AccessMgr accessMgr = AccessMgrFactory.createInstance( TestUtils.getContext() );
            User admin;
            // If these tests are invoked via REST, the admin creds will configured as fortress.properties, otherwise part of the test data.
            if(Config.getInstance().isRestEnabled())
            {
                admin = new User(Config.getInstance().getProperty( GlobalIds.HTTP_UID_PROP ), Config.getInstance().getProperty( GlobalIds.HTTP_PW_PROP ));
            }
            else
            {
                admin = UserTestData.getUser( UserTestData.USERS_TU0[0] );
            }
            adminSess = accessMgr.createSession( admin, false );
        }
        catch ( SecurityException ex )
        {
            String error = " static initializer caught SecurityException rc=" + ex.getErrorId() + ", msg="
                + ex.getMessage();
            LOG.error( error );
        }
        return adminSess;
    }
}
