'Resolve a table alias into the linked table (component, linktable
or free join), and the joins and left joins between the current
resource and the linked table.
@param resource: the current S3Resource
@param alias: the alias
@return: tuple of (linked table, joins, left joins, multiple,
distinct), the two latter being flags to indicate
possible ambiguous query results (needed by the query
builder)
@raise: AttributeError if one of the key fields or tables
can not be found
@raise: SyntaxError if the alias can not be resolved (e.g.
because on of the keys isn\'t a foreign key, points
to the wrong table or is ambiguous)'

@staticmethod
def _resolve_alias(resource, alias):

    if (alias in ('~', resource.alias)):
        return (resource.table, None, False, False)
    multiple = True
    linked = resource.linked
    if (linked and (linked.alias == alias)):
        linktable = resource.table
        ktable = linked.table
        join = [ktable.on((ktable[linked.fkey] == linktable[linked.rkey]))]
        return (ktable, join, multiple, True)
    s3db = current.s3db
    tablename = resource.tablename
    if ((alias not in resource.components) and (alias not in resource.links)):
        _alias = alias
        hook = s3db.get_component(tablename, alias)
        if (not hook):
            _alias = s3db.get_alias(tablename, alias)
            if _alias:
                hook = s3db.get_component(tablename, _alias)
        if hook:
            resource._attach(_alias, hook)
    components = resource.components
    links = resource.links
    if (alias in components):
        component = components[alias]
        ktable = component.table
        join = component._join()
        multiple = component.multiple
    elif (alias in links):
        link = links[alias]
        ktable = link.table
        join = link._join()
    elif ('_' in alias):
        DELETED = current.xml.DELETED
        table = resource.table
        tablename = resource.tablename
        pkey = fkey = None
        (fkey, kname) = (alias.split(':') + [None])[:2]
        if (not kname):
            (fkey, kname) = (kname, fkey)
        ktable = s3db.table(kname, AttributeError(('table    not    found:    %s' % kname)), db_only=True)
        if (fkey is None):
            for fname in ktable.fields:
                (tn, key, m) = s3_get_foreign_key(ktable[fname], m2m=False)
                if (not tn):
                    continue
                if (tn == tablename):
                    if (fkey is not None):
                        raise SyntaxError(('ambiguous    foreign    key    in    %s' % alias))
                    else:
                        fkey = fname
                        if key:
                            pkey = key
            if (fkey is None):
                raise SyntaxError(('no    foreign    key    for    %s    in    %s' % (tablename, kname)))
        else:
            if (fkey not in ktable.fields):
                raise AttributeError(('no    field    %s    in    %s' % (fkey, kname)))
            (tn, pkey, m) = s3_get_foreign_key(ktable[fkey], m2m=False)
            if (tn and (tn != tablename)):
                raise SyntaxError(('%s.%s    is    not    a    foreign    key    for    %s' % (kname, fkey, tablename)))
            elif (not tn):
                raise SyntaxError(('%s.%s    is    not    a    foreign    key' % (kname, fkey)))
        if (pkey is None):
            pkey = table._id.name
        query = (table[pkey] == ktable[fkey])
        if (DELETED in ktable.fields):
            query &= (ktable[DELETED] != True)
        join = [ktable.on(query)]
    else:
        raise SyntaxError(('Invalid    tablename:    %s' % alias))
    return (ktable, join, multiple, True)
