'Resolve the hierarchical lookup in a typeof-query
@param l: the left operand
@param r: the right operand'

@classmethod
def _resolve_hierarchy(cls, l, r):

    from s3hierarchy import S3Hierarchy
    tablename = l.tablename
    hierarchy = S3Hierarchy(tablename)
    if (hierarchy.config is None):
        (ktablename, key) = s3_get_foreign_key(l)[:2]
        if ktablename:
            hierarchy = S3Hierarchy(ktablename)
    else:
        key = None
    list_type = (str(l.type)[:5] == 'list:')
    if ((hierarchy.config is None) and (not list_type)):
        return (False, None, None, None)
    (field, keys) = (l, r)
    if (not key):
        s3db = current.s3db
        table = s3db[tablename]
        if (l.name != table._id.name):
            fs = S3FieldSelector(l.name)
            if list_type:
                expr = fs.contains(r)
            else:
                expr = cls._query_belongs(l, r, field=fs)
            resource = s3db.resource(tablename)
            if (expr is not None):
                subquery = expr.query(resource)
            else:
                subquery = None
            if (not subquery):
                return (True, None, None, None)
            DELETED = current.xml.DELETED
            if (DELETED in table.fields):
                subquery &= (table[DELETED] != True)
            rows = current.db(subquery).select(table._id)
            field = table[hierarchy.pkey.name]
            keys = set([row[table._id.name] for row in rows])
    (nodeset, none) = (None, False)
    if keys:
        none = False
        if (not isinstance(keys, (list, tuple, set))):
            keys = set([keys])
        nodes = set()
        for node in keys:
            if (node is None):
                none = True
            else:
                try:
                    node_id = long(node)
                except ValueError:
                    continue
                nodes.add(node_id)
        if (hierarchy.config is not None):
            nodeset = hierarchy.findall(nodes, inclusive=True)
        else:
            nodeset = nodes
    elif (keys is None):
        none = True
    return (True, field, nodeset, none)
