'Recursively render a human-readable representation of a
S3ResourceQuery.
@param resource: the S3Resource
@param query: the S3ResourceQuery
@param invert: invert the query'

@classmethod
def _render(cls, resource, alias, query, invert=False, labels=None):

    T = current.T
    if (not query):
        return None
    op = query.op
    l = query.left
    r = query.right
    render = (lambda q, r=resource, a=alias, invert=False, labels=labels: cls._render(r, a, q, invert=invert, labels=labels))
    if (op == query.AND):
        l = render(l)
        r = render(r)
        if ((l is not None) and (r is not None)):
            if invert:
                result = (T('NOT    %s    OR    NOT    %s') % (l, r))
            else:
                result = (T('%s    AND    %s') % (l, r))
        else:
            result = (l if (l is not None) else r)
    elif (op == query.OR):
        l = render(l)
        r = render(r)
        if ((l is not None) and (r is not None)):
            if invert:
                result = (T('NOT    %s    AND    NOT    %s') % (l, r))
            else:
                result = (T('%s    OR    %s') % (l, r))
        else:
            result = (l if (l is not None) else r)
    elif (op == query.NOT):
        result = render(l, invert=(not invert))
    else:
        try:
            rfield = l.resolve(resource)
        except (AttributeError, SyntaxError):
            return None
        try:
            values = cls._convert(rfield, r)
        except (TypeError, ValueError):
            values = r
        selector = l.name
        if (labels and (selector in labels)):
            rfield.label = labels[selector]
        if (values is None):
            values = T('None')
        else:
            list_type = (rfield.ftype[:5] == 'list:')
            renderer = rfield.represent
            if (not callable(renderer)):
                renderer = (lambda v: s3_unicode(v))
            if hasattr(renderer, 'linkto'):
                renderer.linkto = None
            is_list = (type(values) is list)
            try:
                if (is_list and hasattr(renderer, 'bulk') and (not list_type)):
                    fvalues = renderer.bulk(values, list_type=False)
                    values = [fvalues[v] for v in values if (v in fvalues)]
                elif list_type:
                    if is_list:
                        values = renderer(values)
                    else:
                        values = renderer([values])
                elif is_list:
                    values = [renderer(v) for v in values]
                else:
                    values = renderer(values)
            except:
                values = s3_unicode(values)
        result = cls._translate_query(query, rfield, values, invert=invert)
    return result
