'List roles/permissions'

def _list(self, r, **attr):

    if r.id:
        return self._edit(r, **attr)
    output = dict()
    if r.interactive:
        T = current.T
        db = current.db
        response = current.response
        resource = self.resource
        auth = current.auth
        options = auth.permission.PERMISSION_OPTS
        NONE = auth.permission.NONE
        get_vars = self.request.get_vars
        table = self.table
        show_matrix = (get_vars.get('matrix', False) and True)
        output.update(title=T('List    of    Roles'))
        sr = auth.get_system_roles()
        undeletable = [sr.ADMIN, sr.ANONYMOUS, sr.AUTHENTICATED]
        resource.add_filter(((~ table.id.belongs(self.HIDE_ROLES)) & (table.hidden != True)))
        resource.load(orderby=table.role, fields=('id', 'role', 'description', 'protected'))
        controllers = [c for c in self.controllers.keys() if (c not in self.HIDE_CONTROLLER)]
        acl_table = auth.permission.table
        query = resource.get_query()
        query = ((query & (acl_table.group_id == self.table.id)) & (acl_table.deleted != True))
        records = db(query).select(acl_table.ALL)
        any = 'ANY'
        acls = Storage({any: Storage()})
        for acl in records:
            c = acl.controller
            f = acl.function
            if (not f):
                f = any
            role_id = acl.group_id
            if (f not in acls):
                acls[f] = Storage()
            if (c not in acls[f]):
                acls[f][c] = Storage()
            acls[f][c][str(role_id)] = Storage(oacl=acl.oacl, uacl=acl.uacl)
        for c in controllers:
            if (c not in acls[any]):
                acls[any][c] = Storage()
            if (any not in acls[any][c]):
                acls[any][c][any] = Storage(oacl=NONE, uacl=NONE)
        columns = []
        headers = [TH('ID'), TH(T('Role'))]
        if show_matrix:
            for c in controllers:
                if (c in acls[any]):
                    headers.append(TH(self.controllers[c].name_nice))
                    columns.append((c, any))
                for f in acls:
                    if ((f != any) and (c in acls[f])):
                        headers.append(TH(self.controllers[c].name_nice, BR(), f))
                        columns.append((c, f))
        else:
            headers += [TH(T('Description'))]
        thead = THEAD(TR(headers))
        trows = []
        for (i, role) in enumerate(resource):
            role_id = role.id
            actions = []
            if (role_id != sr.ADMIN):
                edit_btn = A(T('Edit'), _href=URL(c='admin', f='role', args=[role_id], vars=get_vars), _class='action-btn')
                actions.append(edit_btn)
            if (role_id != sr.ANONYMOUS):
                users_btn = A(T('Users'), _href=URL(c='admin', f='role', args=[role_id, 'users']), _class='action-btn')
                actions.append(users_btn)
            if ((not role.protected) and (role_id not in undeletable)):
                delete_btn = A(T('Delete'), _href=URL(c='admin', f='role', args=[role_id, 'delete'], vars=get_vars), _class='delete-btn')
                actions.append(delete_btn)
            tdata = [TD(actions), TD(role.role)]
            if show_matrix:
                for (c, f) in columns:
                    if ((f in acls) and (c in acls[f]) and (str(role_id) in acls[f][c])):
                        oacl = acls[f][c][str(role_id)].oacl
                        uacl = acls[f][c][str(role_id)].uacl
                    else:
                        oacl = acls[any][c][any].oacl
                        uacl = acls[any][c][any].oacl
                    oaclstr = ''
                    uaclstr = ''
                    for o in options:
                        if ((o == NONE) and (oacl == NONE)):
                            oaclstr = ('%s%s' % (oaclstr, options[o][0]))
                        elif (oacl and (oacl & o)):
                            oaclstr = ('%s%s' % (oaclstr, options[o][0]))
                        else:
                            oaclstr = ('%s-' % oaclstr)
                        if ((o == NONE) and (uacl == NONE)):
                            uaclstr = ('%s%s' % (uaclstr, options[o][0]))
                        elif (uacl and (uacl & o)):
                            uaclstr = ('%s%s' % (uaclstr, options[o][0]))
                        else:
                            uaclstr = ('%s-' % uaclstr)
                    values = ('%s    (%s)' % (uaclstr, oaclstr))
                    tdata += [TD(values, _nowrap='nowrap')]
            else:
                tdata += [TD(T(role.description))]
            _class = (((i % 2) and 'even') or 'odd')
            trows.append(TR(tdata, _class=_class))
        tbody = TBODY(trows)
        items = TABLE(thead, tbody, _class='dataTable    display', _id='datatable')
        s3 = response.s3
        s3.no_formats = True
        s3.actions = []
        s3.no_sspag = True
        from s3data import S3DataTable
        dt = S3DataTable.htmlConfig(items, 'datatable', [[1, 'asc']], dt_pagination=False)
        output['items'] = dt
        add_btn = A(T('Create    Role'), _href=URL(c='admin', f='role', args=['create']), _class='action-btn')
        output['add_btn'] = add_btn
        response.view = 'admin/role_list.html'
    elif (r.representation == 'xls'):
        r.error(501, current.ERROR.BAD_FORMAT)
    else:
        r.error(415, current.ERROR.BAD_FORMAT)
    return output
