'Find all applicable ACLs for the specified situation for
the specified realms and delegations
@param racl: the required ACL
@param realms: the realms
@param delegations: the delegations
@param c: the controller name, falls back to current request
@param f: the function name, falls back to current request
@param t: the tablename
@param entity: the realm entity
@return: None for no ACLs defined (allow),
[] for no ACLs applicable (deny),
or list of applicable ACLs'

def applicable_acls(self, racl, realms=None, delegations=None, c=None, f=None, t=None, entity=[]):

    if (not self.use_cacls):
        return None
    else:
        acls = {}
    if realms:
        roles = set(realms.keys())
        if delegations:
            for role in delegations:
                roles.add(role)
    else:
        return acls
    db = current.db
    table = self.table
    c = (c or self.controller)
    f = (f or self.function)
    page_restricted = self.page_restricted(c=c, f=f)
    query = ((table.deleted != True) & table.group_id.belongs(roles))
    if page_restricted:
        q = (table.function == None)
        if (f and self.use_facls):
            q |= (table.function == f)
        q &= (table.controller == c)
    else:
        q = None
    if (t and self.use_tacls):
        if hasattr(t, '_tablename'):
            t = original_tablename(t)
        tq = (((table.controller == None) & (table.function == None)) & (table.tablename == t))
        q = (tq if (q is None) else (q | tq))
        table_restricted = self.table_restricted(t)
    else:
        table_restricted = False
    if (q is not None):
        query &= q
        rows = db(query).select(table.group_id, table.controller, table.function, table.tablename, table.unrestricted, table.entity, table.uacl, table.oacl, cacheable=True)
    else:
        rows = []
    ANY = 'ANY'
    ALL = (self.ALL, self.ALL)
    NONE = (self.NONE, self.NONE)
    use_facls = self.use_facls
    def rule_type(r):
        if (r.controller is not None):
            if (r.function is None):
                return 'c'
            elif use_facls:
                return 'f'
        elif (r.tablename is not None):
            return 't'
        return None
    most_permissive = (lambda x, y: ((x[0] | y[0]), (x[1] | y[1])))
    most_restrictive = (lambda x, y: ((x[0] & y[0]), (x[1] & y[1])))
    delegation_rows = []
    append_delegation = delegation_rows.append
    use_realms = self.entity_realm
    for row in rows:
        group_id = row.group_id
        if (group_id in delegations):
            append_delegation(row)
        if (group_id not in realms):
            continue
        rtype = rule_type(row)
        if (rtype is None):
            continue
        if use_realms:
            if row.unrestricted:
                entities = [ANY]
            elif (row.entity is not None):
                entities = [row.entity]
            else:
                entities = realms[group_id]
            if (entities is None):
                entities = [ANY]
        else:
            entities = [ANY]
        acl = (row['uacl'], row['oacl'])
        for e in entities:
            if (e in acls):
                eacls = acls[e]
                if (rtype in eacls):
                    eacls[rtype] = most_permissive(eacls[rtype], acl)
                else:
                    eacls[rtype] = acl
            else:
                acls[e] = {rtype: acl}
    if (ANY in acls):
        default = dict(acls[ANY])
    else:
        default = None
    if self.delegations:
        for row in delegation_rows:
            rtype = rule_type(row)
            if (rtype is None):
                continue
            group_id = row.group_id
            if (group_id not in delegations):
                continue
            else:
                drealms = delegations[group_id]
            acl = (row['uacl'], row['oacl'])
            for receiver in drealms:
                drealm = drealms[receiver]
                if entity:
                    if (entity not in drealm):
                        continue
                    else:
                        drealm = [entity]
                if (receiver in acls):
                    dacls = dict(acls[receiver])
                elif (default is not None):
                    dacls = default
                else:
                    continue
                if (rtype in dacls):
                    dacls[rtype] = most_restrictive(dacls[rtype], acl)
                else:
                    dacls[rtype] = acl
                for e in drealm:
                    if (e in acls):
                        for t in ('c', 'f', 't'):
                            if (t in acls[e]):
                                if (t in dacls):
                                    dacls[t] = most_restrictive(dacls[t], acls[e][t])
                                else:
                                    dacls[t] = acls[e][t]
                    acls[e] = dacls
    acl = acls.get(ANY, {})
    if ('c' in acl):
        if ('f' in acl):
            default_page_acl = acl['f']
        else:
            default_page_acl = acl['c']
    elif page_restricted:
        default_page_acl = NONE
    else:
        default_page_acl = ALL
    if ('t' in acl):
        default_table_acl = acl['t']
    elif table_restricted:
        default_table_acl = default_page_acl
    else:
        default_table_acl = ALL
    if ((not acls) and (not (t and self.use_tacls))):
        acls[ANY] = {'c': default_page_acl}
    s3db = current.s3db
    ancestors = set()
    if (entity and self.entity_hierarchy and (s3db.pr_instance_type(entity) == 'pr_person')):
        ancestors = set(s3db.pr_realm(entity))
    result = {}
    for e in acls:
        if (entity and (e != entity) and (e != ANY)):
            if (e in ancestors):
                key = entity
            else:
                continue
        else:
            key = e
        acl = acls[e]
        if ('f' in acl):
            page_acl = most_permissive(default_page_acl, acl['f'])
        elif ('c' in acl):
            page_acl = most_permissive(default_page_acl, acl['c'])
        elif page_restricted:
            page_acl = default_page_acl
        else:
            page_acl = ALL
        if ('t' in acl):
            table_acl = most_permissive(default_table_acl, acl['t'])
        elif table_restricted:
            table_acl = default_table_acl
        else:
            table_acl = ALL
        acl = most_restrictive(page_acl, table_acl)
        if (((acl[0] & racl) == racl) or ((acl[1] & racl) == racl)):
            result[key] = acl
    return result
