class JDBCConnection implements ObjectStoreConnection {

    @Override
    public ResourceAccessList listResourceAccess(String principal, String action, String userDomain) {
        
        final String caller = "listResourceAccess";

        ResourceAccessList rsrcAccessList = new ResourceAccessList();
        List<ResourceAccess> resources = new ArrayList<>();
        rsrcAccessList.setResources(resources);

        // check to see if this an aws request based on
        // the action query
        
        boolean awsQuery = (action != null && action.equals(ZMSConsts.ACTION_ASSUME_AWS_ROLE));
        boolean singlePrincipalQuery = (principal != null && !principal.isEmpty());
        
        // first let's get the principal list that we're asked to check for
        // since if we have no matches then we have nothing to do
        
        Map<String, List<String>> rolePrincipals = getRolePrincipals(principal, awsQuery,
                userDomain, caller);
        if (rolePrincipals.isEmpty()) {
            if (singlePrincipalQuery) {
                
                // so the given principal is not available as a role member
                // so before returning an empty response let's make sure
                // that it has been registered in Athenz otherwise we'll
                // just return 404 - not found exception
                
                if (getPrincipalId(principal) == 0) {
                    throw notFoundError(caller, ZMSConsts.OBJECT_PRINCIPAL, principal);
                }
                
                resources.add(getResourceAccessObject(principal, null));
            }
            return rsrcAccessList;
        }
        
        // now let's get the list of role assertions. if we have
        // no matches, then we have nothing to do
        
        Map<String, List<Assertion>> roleAssertions = getRoleAssertions(action, caller);
        if (roleAssertions.isEmpty()) {
            if (singlePrincipalQuery) {
                resources.add(getResourceAccessObject(principal, null));
            }
            return rsrcAccessList;
        }
        
        // finally we need to get all the trusted role maps
        
        Map<String, List<String>> trustedRoles = getTrustedRoles(caller);
        
        // couple of special cases - if we're asked for action assume_aws_role
        // then we're looking for role access in AWS. So we're going to retrieve
        // the domains that have aws account configured only and update
        // the resource to generate aws role resources. If the action is
        // assume_aws_role with no principal - then another special case to
        // look for actual users only
        
        Map<String, String> awsDomains = null;
        if (awsQuery) {
            awsDomains = getAwsDomains(caller);
        }
        
        // now let's go ahead and combine all of our data together
        // we're going to go through each principal, lookup
        // the assertions for the role and add them to the return object
        // if the role has no corresponding assertions, then we're going
        // to look at the trust role map in case it's a trusted role
        
        Map<String, List<Assertion>> principalAssertions = new HashMap<>();
        for (Map.Entry<String, List<String>> entry : rolePrincipals.entrySet()) {
            
            String roleIndex = entry.getKey();
            
            if (LOG.isDebugEnabled()) {
                LOG.debug(caller + ": processing role: " + roleIndex);
            }
            
            // get the list of principals for this role
            
            List<String> rPrincipals = entry.getValue();
            for (String rPrincipal : rPrincipals) {
                
                if (LOG.isDebugEnabled()) {
                    LOG.debug(caller + ": processing role principal: " + rPrincipal);
                }
                
                // if running an aws query with no principals specified then make
                // sure this is real user and not some service
                
                if (skipAwsUserQuery(awsDomains, principal, rPrincipal, userDomain)) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(caller + ": skipping non-user: " + rPrincipal);
                    }
                    continue;
                }

                List<Assertion> assertions = principalAssertions.computeIfAbsent(rPrincipal, k -> new ArrayList<>());

                // retrieve the assertions for this role
                
                addRoleAssertions(assertions, roleAssertions.get(roleIndex), awsDomains);
                    
                // check to see if this is a trusted role. There might be multiple
                // roles all being mapped as trusted, so we need to process them all
                
                List<String> mappedTrustedRoles = trustedRoles.get(roleIndex);
                if (mappedTrustedRoles != null) {
                    for (String mappedTrustedRole : mappedTrustedRoles) {
                        
                        if (LOG.isDebugEnabled()) {
                            LOG.debug(caller + ": processing trusted role: " + mappedTrustedRole);
                        }
                        
                        addRoleAssertions(assertions, roleAssertions.get(mappedTrustedRole), awsDomains);
                    }
                }
            }
        }
        
        // finally we need to create resource access list objects and return
        
        for (Map.Entry<String, List<Assertion>> entry : principalAssertions.entrySet()) {
            
            // if this is a query for all principals in Athenz then we're
            // automatically going to skip any principals who have no
            // assertions
            
            List<Assertion> assertions = entry.getValue();
            if (!singlePrincipalQuery && (assertions == null || assertions.isEmpty())) {
                continue;
            }
            
            resources.add(getResourceAccessObject(entry.getKey(), assertions));
        }
        
        return rsrcAccessList;
    }

    public  JDBCConnection(Connection con, boolean autoCommit);

}